Django: How to filter Users that belong to a specific group


Question

I'm looking to narrow a query set for a form field that has a foreignkey to the User's table down to the group that a user belongs to.

The groups have been previously associated by me. The model might have something like the following:

    myuser = models.ForeignKey(User)

And my ModelForm is very bare bones:

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

So when I instantiate the form I do something like this in my views.py:

    form = MyForm()

Now my question is, how can I take the myuser field, and filter it so only users of group 'foo' show up.. something like:

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

The query in SQL looks like this:

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

I'd like to avoid using raw SQL though. Is it possible to do so?

1
30
12/9/2016 1:47:53 PM

Accepted Answer

You'll want to use Django's convention for joining across relationships to join to the group table in your query set.

Firstly, I recommend giving your relationship a related_name. This makes the code more readable than what Django generates by default.

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

If you want only a single group, you can join across that relationship and compare the name field using either of these methods:

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

If you want to qualify multiple groups, use the in clause:

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

If you want to quickly see the generated SQL, you can do this:

qs = User.objects.filter(groups__name='foo')
print qs.query 
49
4/24/2015 3:02:12 PM

This is a really old question, but for those googling the answer to this (like I did), please know that the accepted answer is no longer 100% correct. A user can belong to multiple groups, so to correctly check if a user is in some group, you should do:

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

Of course, if you want to check for multiple groups, you can add those to the list:

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

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon