2009-11-27 69 views
26

Estoy buscando limitar un conjunto de consultas para un campo de formulario que tiene una clave externa a la tabla del usuario hasta el grupo al que pertenece un usuario.Django: Cómo filtrar usuarios que pertenecen a un grupo específico

Los grupos han sido previamente asociados por mí. El modelo podría tener algo como lo siguiente:

myuser = models.ForeignKey(User) 

Y mi ModelForm es muy básico:

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

Así que cuando una instancia del formulario que hago algo como esto en mi views.py:

form = MyForm() 

Ahora mi pregunta es, ¿cómo puedo salir al campo miUsuario, y el filtro de modo que sólo los usuarios de 'foo' grupo aparece .. algo así como:

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

La consulta en SQL tiene este aspecto:

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'; 

me gustaría evitar el uso de SQL en bruto sin embargo. ¿Es posible hacerlo?

Respuesta

42

Querrá usar Django's convention for joining across relationships para unirse a la tabla de grupos en su conjunto de consultas.

En primer lugar, recomiendo dar a su relación un related_name. Esto hace que el código sea más legible de lo que Django genera de manera predeterminada.

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

Si desea que sólo un único grupo, puede unirse a través de esa relación y comparar el campo nombre utilizando cualquiera de estos métodos:

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

Si desea calificar múltiples grupos, utilice el in cláusula:

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

Si desea ver rápidamente el SQL generado, se puede hacer esto:

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

Brilliant, gracias Joe. Publiqué el SQL para esto arriba a la derecha cuando publicaste la respuesta. Apreciar los comentarios, funciona excelente. – randombits

+1

No hay problema, volví y lo edité para mostrarle cómo imprimir el SQL para un conjunto de consultas para que pueda compararlo con lo que está esperando. –

13

Esta es una pregunta muy antigua, pero para aquellos que buscan en Google la respuesta a esto (como yo), sepan que la respuesta aceptada ya no es 100% correcta. Un usuario puede pertenecer a varios grupos, por lo que para comprobar correctamente si un usuario está en algún grupo, que debe hacer:

qs = User.objects.filter(groups__name__in=['foo']) 

Por supuesto, si usted quiere comprobar si hay varios grupos, puede agregar los a la lista :

qs = User.objects.filter(groups__name__in=['foo', 'bar']) 
+4

Actualicé mi respuesta para reflejar su preocupación sobre la calificación de grupos múltiples, pero no hay nada de malo en usar '=' en lugar de 'en' si está intentando limitar a un solo grupo. –

+1

Seconding @JoeHolloway aquí. El formato 'User.objects.filter (groups__name = 'foo')' funciona perfectamente bien cuando se consultan usuarios en un solo grupo. – CoreDumpError

Cuestiones relacionadas