2009-11-27 5 views
26

Я ищу, чтобы сузить набор запросов для поля формы, который имеет посторонний ключ в таблице пользователя до группы, к которой принадлежит пользователь.Django: Как фильтровать пользователей, принадлежащих к определенной группе

Группы были ранее связаны мной. Модель может иметь что-то вроде следующего:

myuser = models.ForeignKey(User) 

И мой ModelForm очень голые кости:

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

Так что, когда я создаю экземпляр форму я сделать что-то подобное в моей views.py:

form = MyForm() 

Теперь мой вопрос, как я могу взять поле MyUser и отфильтровать его так только пользователи «Foo» группы показать .. что-то вроде:

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

Запрос в SQL выглядит следующим образом:

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

Я хотел бы, чтобы избежать использования сырой SQL, хотя. Можно ли это сделать?

ответ

42

Вы должны использовать Django's convention for joining across relationships, чтобы присоединиться к таблице групп в вашем запросе.

Во-первых, я рекомендую дать ваши отношения related_name. Это делает код более читаемым, чем по умолчанию Django.

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

Если вы хотите только одну группу, вы можете присоединиться через эти отношения и сравнить имя поля, используя один из следующих методов:

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

Если вы хотите, чтобы претендовать несколько групп, используйте in пункт:

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

Если вы хотите быстро увидеть сгенерированный SQL, вы можете сделать это:

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

Блестящий, спасибо Джо. Я разместил SQL для этого выше, когда вы отправили ответ. Цените отзывы, отлично работают. – randombits

+1

Нет, я вернулся и отредактировал его, чтобы показать вам, как распечатать SQL для набора запросов, чтобы вы могли сравнить его с тем, что вы ожидаете. –

13

Это действительно старый вопрос, но для тех, кто отвечает на этот вопрос (как и я), пожалуйста, знайте, что принятый ответ больше не на 100% правильный. Пользователь может принадлежать нескольким группам, таким образом, чтобы правильно проверить, если пользователь находится в какой-то группе, вы должны сделать:

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

Конечно, если вы хотите, чтобы проверить на несколько групп, вы можете добавить их в список :

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

Я обновил свой ответ, чтобы отразить вашу озабоченность по поводу квалификации нескольких групп, но нет ничего плохого в использовании «=», а не «in», если вы пытаетесь ограничить одну группу. –

+1

Вторичный @JoeHolloway здесь. Формат 'User.objects.filter (groups__name = 'foo')' отлично работает при запросе для пользователей в одной группе. – CoreDumpError

Смежные вопросы