Django:如何过滤属于特定组的用户

42

我想缩小一个查询集,使其针对一个表单字段,该字段具有对用户表的外键,并仅限于用户所属的组。

这些组之前已经被我关联起来了。模型可能会像以下内容一样:

myuser = models.ForeignKey(User)

我的ModelForm非常基础:

class MyForm(ModelForm):
    class Meta:
        model = MyModel

所以当我在views.py中实例化表单时,我会做这样的事情:

form = MyForm()

我的问题是,如何获取'myuser'字段并将其过滤,以便只显示属于'foo'组的用户..类似这样:

form.fields["myuser"].queryset = ???

SQL中的查询如下所示:

mysql> SELECT * from auth_user INNER JOIN auth_user_groups ON auth_user.id = auth_user_groups.user_id INNER JOIN auth_group ON auth_group.id = auth_user_groups.group_id WHERE auth_group.name = 'client';

我想避免使用原始的SQL语句。但是有没有可能做到这一点?

2个回答

66
你需要使用Django跨关系加入的约定来在查询集中加入到组表。

首先,我建议给你的关系设置一个related_name。这比Django默认生成的代码更易读。

class Group(models.Model):
    myuser = models.ForeignKey(User, related_name='groups')

如果你只想要单个分组,你可以通过连接该关系并使用以下任意一种方法比较名称字段来实现:

form.fields['myuser'].queryset = User.objects.filter(
    groups__name='foo')
form.fields['myuser'].queryset = User.objects.filter(
    groups__name__in=['foo'])

如果您想要匹配多个组,请使用in子句:

form.fields['myuser'].queryset = User.objects.filter(
    groups__name__in=['foo', 'bar'])

如果你想快速查看生成的SQL,可以这样做:

qs = User.objects.filter(groups__name='foo')
print qs.query 

太棒了,谢谢Joe。我在你回答之前就已经发布了这个SQL。非常感谢你的反馈,运行得非常好。 - randombits
1
没问题,我回去编辑了一下,向你展示如何打印出查询集的SQL,这样你就可以将其与预期结果进行比较。 - Joe Holloway

29

这是一个很老的问题,但对于那些像我一样通过Google寻找答案的人,请知道已经接受的答案不再100%正确了。用户可以属于多个组,因此要正确地检查用户是否属于某个组,应该执行以下操作:

qs = User.objects.filter(groups__name__in=['foo'])
当然,如果你想检查多个群组,可以将它们添加到列表中:
qs = User.objects.filter(groups__name__in=['foo', 'bar'])

4
我更新了我的回答以反映你对资格认证多个组的关注,但如果你想限制为单个组,则使用“=”而不是“in”没有问题。 - Joe Holloway
1
在这里支持@JoeHolloway的观点。当查询单个组中的用户时,“User.objects.filter(groups__name ='foo')”格式完全正常。 - coredumperror

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接