Преобразование 'not in' SQL-запроса в синтаксис Django

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

В Django фильтрация объектов модели по наличию или отсутствию конкретных значений в списке осуществляется с помощью методов filter и exclude. Они используются с оператором __in.

Примеры использования:

Python
Скопировать код
# Выборка объектов, удовлетворяющих условию:
YourModel.objects.filter(field__in=[values])

# Исключение объектов, не удовлетворяющих условию:
YourModel.objects.exclude(field__in=[values])
  • Оператор __in совместим со всеми перечислительными типами данных.
  • Вместо YourModel подставьте название вашей модели.
  • field и [values] замените на имя поля модели и список значений, предназначенных для фильтрации или исключения.
Кинга Идем в IT: пошаговый план для смены профессии

Использование подзапросов для исключений

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

Python
Скопировать код
leave_out_ids = Table2.objects.filter(your_condition).values_list('id', flat=True)
Table1.objects.exclude(id__in=leave_out_ids)

Уточнения:

  • your_condition определяет фильтр для таблицы Table2.
  • exclude исключает из таблицы Table1 записи, чей id присутствует в списке leave_out_ids.
  • Параметр flat=True позволяет возвратить список id вместо списка кортежей.

Обработка связанных моделей

При наличии связи через ForeignKey воспользуйтесь следующим синтаксисом:

Python
Скопировать код
YourModel.objects.exclude(related_table__field=value)

Таким образом, мы исключаем объекты, связанные с моделью, где поле соответствует указанному значению value.

Формирование сложных запросов при помощи Q-объектов

Для построения сложных запросов применяются Q-объекты:

Python
Скопировать код
from django.db.models import Q

condition = ~Q(related_table__field=value)
YourModel.objects.filter(condition)
  • Знак ~ инверсирует условие Q-объекта.
  • Q-объекты можно сохранять в переменные для простоты восприятия кода.

Исполнение собственных SQL-запросов и рекомендации по оптимизации производительности

В Django можно выполнить кастомный SQL-запрос через objects.extra:

Python
Скопировать код
YourModel.objects.extra(where=["field NOT IN (SELECT field FROM Table2 ...)"])

Важно помнить следующее:

  • Не забывайте про защиту от SQL-инъекций.
  • Оптимизация SQL-запросов повысит производительность.

Визуализация

Для наглядного понимания принципа работы фильтров in/not in, рассмотрим пример:

Markdown
Скопировать код
Сокровищница (🧳): [Золотая Монета (💰), Серебряное Кольцо (💍), Рубин (🔴)]

Получить определённые предметы можно так:

Python
Скопировать код
Treasure.objects.filter(item__in=['💰', '🔴']) 
# Собираем все Золотые Монеты и Рубины
Markdown
Скопировать код
Найденные сокровища: [Золотая Монета (💰), Рубин (🔴)]
# Вот они!

Исключить ненужные нам предметы можно следующим образом:

Python
Скопировать код
Treasure.objects.exclude(item__in=['💍'])  
# Прощай, Серебряное Кольцо!
Markdown
Скопировать код
Оставшиеся сокровища: [Золотая Монета (💰), Рубин (🔴)]
# Звёзды нашего шоу!

Управлять запросами в Django с помощью in/not in столь же легко.

Разные случаи и их решения

Большой список значений? Не проблема!

При работе с большими списками значений лучше использовать подзапросы:

Python
Скопировать код
big_values = range(int(1e6))
YourModel.objects.filter(field__in=big_values)

Такой подход также допустим:

Python
Скопировать код
YourModel.objects.exclude(field__in=AnotherModel.objects.all().values_list('field', flat=True))

Будьте осмотрительны с NULL значениями и NOT IN!

Обращение с NULL значениями и оператором NOT IN может быть коварным:

Python
Скопировать код
YourModel.objects.exclude(field__in=nullable_values)

Для корректной обработки NULL используйте два условия:

Python
Скопировать код
YourModel.objects.exclude(field__in=nullable_values).exclude(field__isnull=True)

Реализация логики 'not in'

Для реализации собственной логики 'not in' можно применять пользовательские операторы сравнения:

Python
Скопировать код
from django.db.models import Lookup

class NotIn(Lookup):
    lookup_name = 'not_in'

    def as_sql(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return '%s NOT IN (%s)' % (lhs, rhs), params

YourModel.objects.get_queryset().filter(field__not_in=[values])

При использовании пользовательских операторов не забывайте о читаемости и производительности кода.

Полезные материалы

  1. Справочник по API QuerySet, Django Documentation – описание использования __in в QuerySets Django.
  2. Создание запросов, Django Documentation – детальное руководство по созданию запросов в Django.
  3. Справочник по API QuerySet, Django Documentation – основы применения exclude() в Django.
  4. ORM Django (Querysets), HonKit – путь к освоению ORM и QuerySets в Django.
  5. Учебник Django, часть 3: Использование моделей, Mozilla – инструкция по использованию моделей Django.
  6. Как просмотреть исходные SQL-запросы, выполняемые Django?, Stack Overflow – советы по просмотру SQL-запросов в Django.
  7. Объект Q, возвращающий false, Stack Overflow – обсуждение создания Q-объектов, всегда возвращающих ложное значение.