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

../_images/usertable.png

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

Частым требованием является выполнение фильтрации OR с двумя и более условиями. Скажем, вы хотите найти всех пользователей с именем, начинающимся на „R“, и фамилией, начинающейся на „D“.

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

  • queryset_1 | queryset_2

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

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

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

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

Аналогичным образом наш ORM-запрос будет выглядеть следующим образом

queryset = User.objects.filter(
        first_name__startswith='R'
    ) | User.objects.filter(
    last_name__startswith='D'
)
queryset
<QuerySet [<User: Ricky>, <User: Ritesh>, <User: Radha>, <User: Raghu>, <User: rishab>]>

Вы также можете посмотреть на сгенерированный запрос.

In [5]: str(queryset.query)
Out[5]: '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% OR "auth_user"."last_name"::text LIKE D%)'

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

from django.db.models import Q
qs = User.objects.filter(Q(first_name__startswith='R')|Q(last_name__startswith='D'))

Если вы посмотрите на сформированный запрос, результат будет точно таким же

In [9]: str(qs.query)
Out[9]: '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% OR "auth_user"."last_name"::text LIKE D%)'
Вернуться на верх