3. Как делать AND-запросы в Django ORM?

../_images/usertable.png

Если вы используете django.contrib.auth, у вас будет таблица под названием auth_user. В ней будут поля username, first_name, last_name и другие.

Часто возникает необходимость выполнить операцию AND, чтобы найти наборы запросов, соответствующие нескольким критериям.

Допустим, вы хотите найти пользователей, у которых firstname начинается с „R“ И last_name начинается с „D“.

Django предоставляет три варианта.

  • filter(<condition_1>, <condition_2>)

  • queryset_1 & queryset_2

  • filter(Q(<condition_1>) & Q(<condition_2>))

3.1. Запрос в деталях

Наш SQL-запрос для приведенного выше условия будет выглядеть примерно так

SELECT username, first_name, last_name, email FROM auth_user WHERE first_name LIKE 'R%' AND last_name LIKE 'D%';
../_images/sqluser_result2.png

Стандартным способом объединения нескольких условий в filter является AND, поэтому вы можете просто сделать.

queryset_1 = User.objects.filter(
    first_name__startswith='R',
    last_name__startswith='D'
)

В качестве альтернативы вы можете явно использовать оператор & для наборов запросов.

queryset_2 = User.objects.filter(
    first_name__startswith='R'
) & User.objects.filter(
    last_name__startswith='D'
)

Для полной настраиваемости можно использовать объекты Q.

queryset_3 = User.objects.filter(
    Q(first_name__startswith='R') &
    Q(last_name__startswith='D')
)


queryset_1
<QuerySet [<User: Ricky>, <User: Ritesh>, <User: rishab>]>

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

In [10]: str(queryset_2.query)
Out[10]: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE ("auth_user"."first_name"::text LIKE R% AND "auth_user"."last_name"::text LIKE D%)'

In [11]: str(queryset_1.query) == str(queryset_2.query) == str(queryset_3.query)
Out[11]: True
Вернуться на верх