You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django多对多(含中间表):单查询获取用户权限卡片及所有权状态

Django单查询获取用户可访问卡片及所有权状态

现有Django模型

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=100)
    # 其他业务字段

class Card(models.Model):
    title = models.CharField(max_length=100)
    # 其他业务字段

class Permissions(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name='card_permissions')
    card = models.ForeignKey(Card, on_delete=models.CASCADE, related_name='user_permissions')
    is_owner = models.BooleanField(default=False)
    # 其他权限控制字段

单查询实现方案

通过annotate结合Case/When表达式,关联Permissions表完成单次查询,同时获取卡片信息与所有权状态:

from django.db.models import Case, When, BooleanField, Value

# 替换为目标用户的ID
target_person_id = 1

# 执行查询
accessible_cards = Card.objects.filter(
    user_permissions__person_id=target_person_id
).annotate(
    is_owner=Case(
        When(user_permissions__person_id=target_person_id, user_permissions__is_owner=True, then=Value(True)),
        default=Value(False),
        output_field=BooleanField()
    )
).distinct()

代码说明

  • filter:筛选出当前用户有权访问的所有卡片
  • annotate:通过条件判断为每张卡片添加is_owner字段,标记是否为当前用户所有
  • distinct:避免因Permissions表关联产生的重复卡片记录

查询结果示例

返回的QuerySet中每个Card实例会携带额外的is_owner属性,示例数据如下:

<Card: 会员卡A>, is_owner=True
<Card: 优惠券B>, is_owner=False
<Card: 储值卡C>, is_owner=True

对应理想SQL逻辑

该Django查询生成的SQL与你期望的逻辑完全匹配,大致SQL语句如下:

SELECT DISTINCT "card".*,
       CASE WHEN "permissions"."is_owner" THEN TRUE ELSE FALSE END AS "is_owner"
FROM "card"
INNER JOIN "permissions" ON ("card"."id" = "permissions"."card_id")
WHERE "permissions"."person_id" = 1;

内容的提问来源于stack exchange,提问作者Nuubles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:07:29