queryset - objects.filter django
Anotaciones de ORM de Django: grupo de consulta de usuario más común (3)
Tengo un QuerySet del modelo auth.User.
Quiero saber: qué grupos son los que contienen la mayoría de estos usuarios.
Ejemplo: tengo tres grupos, con estos usuarios:
- g1: u1 u2 u3 u4
- g2: u1 u2
- g3: u1 u4 u5 u6
- g4: u5 u6 u7
User-QuerySet: u1 u2 u3
Resultado (contando los miembros que están en el User-Queryset dado):
- g1: cuenta 3
- g2: cuenta 2
- g3: cuenta 1
- g4: cuenta 0
¿Cómo puedo obtener un QuerySet anotado del modelo Agrupar esto con Django 1.8?
Caso de uso
Muestre cuántos miembros tiene "x" en el nombre de usuario que tiene cada grupo.
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;
Actualizar
El grupo g4
no tiene miembros coincidentes, pero debe estar en el QuerySet anotado.
En Django podemos agrupar el objeto en función de los values
y podemos aplicar la annotation
en el resultado de la agrupación. Lea este enlace que explicará cómo usar los valores y la anotación.
group = Group.objects.filter(id=XX).values("user").annotate(Count("user__pk"))
Si solo necesita los usuarios del grupo significa:
group = Group.objects.annotate(Count("user__pk"))
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())),
)
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()])
Espero que esta respuesta sea aceptable ...