我最近将 Django 更新到最先进的版本 1.11rc1,因为那里引入了子查询功能。
现在,假设这是我的用例:我有以下模型 - 用户、组和权限。所以,我有一些我可以分组的用户(例如管理员组)和权限 - 这是可以做一些事情的用户列表(例如,我有用户 A、用户 B 和可以创建新用户的管理员)。我现在要做的是有效地显示所有权限,其中包含许多用户。所以换句话说,我想创建一个 QuerySet,它会返回有关权限的所有信息并计算每个权限的用户数。解决此问题的第一个显而易见的方法是创建一个get_user_count
Permission 模型的方法,它将从我的 ManyToMany 关系中返回所有用户,但这将需要每个 Permission 至少 1 个额外的查询,这对我来说是不可接受的,因为我计划拥有很多 Permission。这是我想使用的地方Subquery
。
所以,澄清一下 - 这是models.py:
class User(models.Model):
name = models.CharField(max_length=20)
class Group(models.Model):
users = models.ManyToManyField(User)
class Permission(models.Model):
users = models.ManyToManyField(User)
groups = models.ManyToManyField(Group)
我想创建一个查询集,它将返回所有权限,里面有很多用户。举例来说,假设我只想包含属于我的组的用户 - 所以我会有这样的事情:
groups = Group.objects.filter(permission=OuterRef('pk'))
users = User.objects.filter(group__in=groups)
queryset = Permission.objects.annotate(
user_no=Subquery(users.annotate(c=Count('*')).values('c'))
)
这里的问题是我OuterRef
无法解决“子查询的过滤器过滤器”中使用的问题:
This queryset contains a reference to an outer query and may only be used in a subquery.
虽然,当我使用另一个子查询来获取组时:
groups = Group.objects.filter(permission=OuterRef(OuterRef('pk')))
users = User.objects.filter(group__in=Subquery(groups))
queryset = Permission.objects.annotate(
user_no=Subquery(users.annotate(c=Count('*')).values('c'))
)
我在第一行得到一个错误:
int() argument must be a string, a bytes-like object or a number, not 'OuterRef'
其余的行无关紧要,对错误没有影响。奇怪的是,文档中出现了完全相同的语法:https ://docs.djangoproject.com/en/dev/ref/models/expressions/#django.db.models.OuterRef
问题是:我做错了什么?或者如何以其他方式(尽管有效)实现我想要的?