我想找到至少属于一组的所有用户。
我找到了解决方法
from django import setup
setup()
from django.contrib.auth.models import User
user_without_group = User.objects.update_or_create(username='user-without-group')[0]
user_without_group.groups.clear()
query = User.objects.filter(groups__isnull=False).values_list('username', flat=True)
print (query.query)
print list(query)
assert user_without_group.username not in query
...但是解决方案不是很好。是否有比groups__isnull=False
更明显的解决方案?
更新
为什么我认为此解决方案不好:我认为这并不明显。阅读和理解并不容易。如果您向了解Python但从未使用过django ORM的人展示此内容,我认为他不会立即理解这意味着什么。
User.objects.filter(groups__isnull=False)
答案 0 :(得分:5)
我不确定您对groups__isnull=False
有什么看法;绝对好请注意,尽管它与groups=None
完全等效,但是您可能会发现它更好一些。
答案 1 :(得分:2)
您也可以这样做:
Group.objects.values_list('user').distinct('user')
您将仅拥有1个或更多Group
的唯一用户。
答案 2 :(得分:1)
User.objects.filter(groups__isnull=False).values_list('username')
产生简单的SQL:
SELECT "users_user"."username" FROM "users_user"
INNER JOIN "users_user_groups" ON ("users_user"."id" = "users_user_groups"."user_id")
WHERE "users_user_groups"."group_id" IS NOT NULL
在docs中显示完全相同的fk上过滤null。
答案 3 :(得分:1)
一种针对SQL实现的较少解决方案是使用Exists
子查询或Count
User.objects.annotate(
has_groups=Exists(
User.groups.through.objects.filter(
user=OuterRef('pk'),
)
)
).filter(has_groups=True)
User.objects.annotate(
groups_count=Count('groups'),
).filter(groups__gte=1)
我怀疑这些解决方案的执行速度是否会比groups__isnull=True
的内部联接更快。如果m2m字段公开了__exists
查找,那么您可以执行filter(groups__exists=True)
并避免大部分重复步骤。
答案 4 :(得分:1)
您可以考虑添加一个可读的自定义查找字段,例如Custom Lookups的group__at_least_one=True