2009-11-27 9 views
26

Je cherche à réduire un ensemble de requêtes pour un champ de formulaire qui a une clé étrangère à la table de l'utilisateur jusqu'au groupe auquel appartient un utilisateur.Django: Comment filtrer les utilisateurs appartenant à un groupe spécifique

Les groupes ont été précédemment associés par moi. Le modèle pourrait avoir quelque chose comme ce qui suit:

myuser = models.ForeignKey(User) 

Et mon ModelForm est os nus:

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

Alors, quand j'instancier la forme que je fais quelque chose comme ça dans mon views.py:

form = MyForm() 

maintenant, ma question est, comment puis-je prendre le champ myuser et filtrer les utilisateurs afin que de « foo » groupe apparaissent .. quelque chose comme:

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

La requête SQL ressemble à ceci:

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

Je voudrais éviter d'utiliser SQL cru bien. Est-il possible de le faire?

Répondre

42

Vous devez utiliser Django's convention for joining across relationships pour rejoindre la table de groupe dans votre ensemble de requêtes.

Premièrement, je recommande de donner à votre relation un related_name. Cela rend le code plus lisible que ce que Django génère par défaut.

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

Si vous voulez un seul groupe, vous pouvez vous joindre à travers cette relation et comparer le champ de nom en utilisant l'une de ces méthodes:

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

Si vous souhaitez bénéficier de plusieurs groupes, utilisez le in clause:

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

Si vous voulez voir rapidement le SQL généré, vous pouvez le faire:

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

Brillant, merci Joe. J'ai posté le code SQL ci-dessus à droite lorsque vous avez posté la réponse. Appréciez les commentaires, fonctionne très bien. – randombits

+1

Aucun prob, je suis revenu et édité pour vous montrer comment imprimer le SQL pour un jeu de requête afin que vous puissiez le comparer à ce que vous attendez. –

13

Ceci est une question très ancienne, mais pour ceux qui recherchent la réponse à cette question (comme je l'ai fait), sachez que la réponse acceptée n'est plus à 100% correcte. Un utilisateur peut appartenir à plusieurs groupes, afin de vérifier correctement si un utilisateur est en quelque groupe, vous devez faire:

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

Bien sûr, si vous voulez vérifier pour plusieurs groupes, vous pouvez les ajouter à la liste :

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

J'ai mis à jour ma réponse pour refléter votre préoccupation concernant la qualification de plusieurs groupes, mais il n'y a rien de mal à utiliser '=' par opposition à 'dans' si vous essayez de limiter à un seul groupe. –

+1

Appuyant @JoeHolloway ici. Le format 'User.objects.filter (groups__name = 'foo')' fonctionne parfaitement lors de l'interrogation des utilisateurs dans un seul groupe. – CoreDumpError

Questions connexes