【问题标题】:Django ORM Annotations: Most common group of user querysetDjango ORM 注释:最常见的用户查询集组
【发布时间】:2016-06-22 04:26:34
【问题描述】:

我有一个 auth.User 模型的 QuerySet。

我想知道:哪些组包含这些用户最多。

示例:我有三个组,有这些用户:

  • g1: u1 u2 u3 u4
  • g2: u1 u2
  • g3: u1 u4 u5 u6
  • g4: u5 u6 u7

用户查询集:u1 u2 u3

结果(计算给定 User-Queryset 中的成员):

  • g1:计数 3
  • g2:计数 2
  • g3:计数 1
  • g4:计数 0

如何使用 Django 1.8 获得模型组的带注释的 QuerySet?

用例

显示每个组有多少用户名中带有“x”的成员。

SQL

SELECT auth_group.id, auth_group.name, 
 (SELECT COUNT(auth_user_groups.id) FROM auth_user_groups WHERE
    auth_user_groups.group_id = auth_group.id AND
    auth_user_groups.user_id IN (SELECT auth_user.id FROM auth_user WHERE username LIKE '%x%')) AS user_cnt 
FROM auth_group ORDER BY user_cnt DESC;

更新

g4 没有匹配的成员,但它应该在带注释的 QuerySet 中。

【问题讨论】:

    标签: django django-models orm


    【解决方案1】:
    from django.db.expressions import Case, When
    from django.db.models import Count, IntegerField
    
    Group.objects.annotate(
        user_cnt=Count(Case(When(user__in=user_list, then=1),
                            output_field=IntegerField())),
    )
    

    【讨论】:

    • 很好,您的回答有效。生成的 SQL:SELECT "auth_group"."id", "auth_group"."name", COUNT(CASE WHEN "auth_user_groups"."user_id" IN (SELECT U0."id" FROM "auth_user" U0 WHERE U0."username"::text LIKE testfoobar%) THEN 1 ELSE NULL END) AS "user_cnt" FROM "auth_group" LEFT OUTER JOIN "auth_user_groups" ON ( "auth_group"."id" = "auth_user_groups"."group_id" ) GROUP BY "auth_group"."id", "auth_group"."name" ORDER BY "user_cnt" DESC
    【解决方案2】:
    list_group = []
    for grp in Group.objects.filter(id__in = [g1, g2, g3, g4]):
        print grp, '---', User.objects.filter(id__in = [u1, u2, u3], groups = grp).count()
        list_group([grp, User.objects.filter(id__in = [u1, u2, u3], groups = grp).count()])
    

    希望这个答案是可以接受的..

    【讨论】:

    • 是的,这可行,但我更喜欢 SQL 中的循环而不是 python 中的循环。 “如何使用 Django 1.8 获得模型组的注释查询集?”
    【解决方案3】:

    在 Django 中,我们可以根据 values 对某个对象进行分组,我们可以将 annotation 应用于分组结果。 阅读此link,它将解释如何使用值和注释。

    group =  Group.objects.filter(id=XX).values("user").annotate(Count("user__pk"))
    

    如果只需要组下的用户意味着:

    group = Group.objects.annotate(Count("user__pk"))
    

    【讨论】:

    • 结果应该是组实例的注释查询集。输入是用户实例的查询集。我在您的示例中看不到这一点。
    猜你喜欢
    • 1970-01-01
    • 2019-10-13
    • 2020-01-26
    • 2018-04-11
    • 2018-08-26
    • 1970-01-01
    • 2018-06-21
    • 1970-01-01
    • 2021-07-25
    相关资源
    最近更新 更多