Django ORM:至少有一个组的所有用户

Django ORM:至少有一个组的所有用户,django,django-queryset,Django,Django Queryset,我想找到至少在一个组中的所有用户 我找到了解决办法 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.filte

我想找到至少在一个组中的所有用户

我找到了解决办法

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
。。。但解决办法并不好。有比组更明显的解决方案吗

更新

为什么我认为这个解决方案不好:我认为这并不明显。它不容易阅读和理解。如果您将此展示给了解Python但从未使用过django ORM的人,我认为他不会立即理解这意味着什么

User.objects.filter(groups__isnull=False)
您还可以执行以下操作:

Group.objects.values_list('user').distinct('user')

而且,只有一个或多个组才能获得唯一用户。

我不确定您对组有什么反对意见\uuu isnull=False;绝对没问题。但是请注意,它与groups=None完全等效,您可能会发现这一点更好。

User.objects.filtergroups\uuuu isnull=False。value\u 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

在fk上过滤null与中显示的完全相同。

不太适合SQL实现的解决方案是使用Exists子查询或计数


不过,我怀疑这些解决方案的执行速度会比groups\uu isnull=True的内部连接快多少。如果M2M字段暴露了一个“存在的查找”,那么你就可以做FieldGysPySysOrth= Trand,避免大部分的样板。

< P>你可以考虑添加一个可读的自定义查找字段,比如GypPyAtAtasListasOne=Trase< /P>为什么你认为这个解决方案不好?@ IVISSAI我更新了这个问题并解释了为什么我认为这不是。很好。如果是可读性问题,我想你有两个选择,第一个是用注释解释你的查询,顺便说一句,我发现这是一个很好的实践,因为理解查询的意图并不总是很容易的。第二种方法是使用更有意义的名称编写自定义查找,比如说“exists”,这样您的查询就变成User.objects.filtergroups\uuuu exists=False。这个查找应该和te IsNull查找一样。@ivissani我读过《干净的代码》和《干净的编码器》这两本书,从那以后我就避免了评论。评论是谎言。就在五分钟前,我遇到了一个老掉牙的评论。代码更改了,变量和方法名称很容易理解。该评论已注明日期。我删除了它,因为它是错误的,在本例中不需要。我发现Django中另一个有用的做法是覆盖模型的queryset,以添加公共过滤器作为方法。因此,您可以向用户queryset添加一个方法,该方法使用_组或任何您认为合适的方法调用,该方法在内部执行过滤。然后您实现了两件事:一是模块化代码,以便将来的更改可以轻松实现;二是可以更详细地描述您正在尝试做的事情。我猜你的意思是groups=None是groups的反面。User.objects.excludegroups=None是用来获取你想要的东西的方法after@guettli我会使用它并添加这样的注释:确保用户至少有一个组,注释也是python代码,您可以/应该使用它们来增加代码的清晰度。是的,filtergroups\uuuu exists=True将非常好。
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)