Справочник по API поиска

Этот документ содержит ссылки на API для поиска, API Django для построения WHERE запроса к базе данных. Чтобы узнать, как использовать поиски, смотрите Создание запросов; чтобы узнать, как создавать новые поиски, смотрите Как писать пользовательские поисковые запросы.

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

У Django есть два базовых класса, которые следуют API-интерфейсу выражения запроса и откуда берутся все встроенные поиски Django:

  • Lookup: для поиска поля (например, exact из field_name__exact)
  • Transform: для преобразования поля

Выражение поиска состоит из трех частей:

  • Часть полей (например, Book.objects.filter(author__best_friends__first_name...);
  • Преобразуемая часть (может быть опущена) (например, __lower__first3chars__reversed);
  • Поиск (например, __icontains), который, если не указан, по умолчанию равен __exact.

API регистрации

Django использует RegisterLookupMixin для предоставления классу интерфейса для регистрации поиска на самом себе или своих экземплярах. Два ярких примера - Field, базовый класс всех полей модели, и Transform, базовый класс всех трансформаций Django.

class lookups.RegisterLookupMixin

Миксин, который реализует API поиска в классе.

classmethod register_lookup(lookup, lookup_name=None)

Регистрирует новый поиск в классе или экземпляре класса. Например:

DateField.register_lookup(YearExact)
User._meta.get_field("date_joined").register_lookup(MonthExact)

зарегистрирует YearExact поиск по DateField и MonthExact поиск по User.date_joined (для получения экземпляра одного поля можно использовать Field Access API). Он переопределяет уже существующий поиск с тем же именем. Поиски, зарегистрированные на экземплярах полей, имеют приоритет над поисками, зарегистрированными на классах. Для данного поиска будет использовано значение lookup_name, если оно указано, в противном случае будет использовано значение lookup.lookup_name.

get_lookup(lookup_name)

Возвращает Lookup с именем lookup_name, зарегистрированный в классе или экземпляре класса, в зависимости от того, что его вызывает. Реализация по умолчанию рекурсивно просматривает все родительские классы и проверяет, есть ли в каком-либо из них зарегистрированный поиск с именем lookup_name, возвращая первое совпадение. Поиск экземпляра будет переопределять поиск класса с тем же именем lookup_name.

get_lookups()

Возвращает словарь каждого имени поиска, зарегистрированного в классе или экземпляре класса, сопоставленного с классом Lookup.

get_transform(transform_name)

Возвращает Transform с именем transform_name, зарегистрированным в классе или экземпляре класса. Реализация по умолчанию рекурсивно просматривает все родительские классы на предмет наличия в них зарегистрированного преобразования с именем transform_name, возвращая первое совпадение.

Чтобы класс был поиском, он должен следовать API выражения запроса. Lookup и Transform естественно следуют этому API.

Changed in Django 4.2:

Добавлена поддержка регистрации поиска на экземплярах Field.

API выражения запроса

API выражений запросов - это общий набор методов, классы которых определяют для использования в выражениях запросов для преобразования себя в выражения SQL. Прямые ссылки на поля, агрегаты и Transform являются примерами, которые следуют этому API. Говорят, что класс следует API-интерфейсу выражения запроса, когда он реализует следующие методы:

as_sql(compiler, connection)

Создает фрагмент SQL для выражения. Возвращает кортеж (sql, params), где sql - строка SQL, а params - список или кортеж параметров запроса. compiler - это объект SQLCompiler, который имеет метод compile(), который можно использовать для компиляции других выражений. connection - это соединение, используемое для выполнения запроса.

Вызов expression.as_sql() обычно некорректен - вместо этого следует использовать compiler.compile(expression). Метод compiler.compile() позаботится о вызове специфичных для поставщика методов выражения.

Пользовательские аргументы ключевых слов могут быть определены в этом методе, если существует вероятность, что методы или подклассы as_vendorname() должны будут предоставить данные для переопределения генерации строки SQL. Смотрите Func.as_sql() для примера использования.

as_vendorname(compiler, connection)

Работает как as_sql() метод. Когда выражение компилируется с помощью compiler.compile(), Django сначала попытается вызвать as_vendorname(), где vendorname - это имя поставщика серверной части, используемой для выполнения запроса. Vendorname является одним из postgresql, oracle, sqlite или mysql для встроенных бэкэндов Django.

get_lookup(lookup_name)

Должен вернуть поиск с именем lookup_name. Например, возвращая self.output_field.get_lookup(lookup_name).

get_transform(transform_name)

Должен вернуть поиск с именем transform_name. Например, возвращая self.output_field.get_transform(transform_name).

output_field

Определяет тип класса, возвращаемого методом get_lookup(). Это должен быть экземпляр Field.

Справочник по Transform

class Transform[исходный код]

Transform - это универсальный класс для реализации преобразований поля. Ярким примером является __year, который преобразует DateField в IntegerField.

Обозначение для использования Transform в поисковом выражении: <expression>__<transformation> (например, date__year).

Этот класс следует за API запроса, что подразумевает, что вы можете использовать <expression>__<transform1>__<transform2>. Это специализированное Func () выражение, которое принимает только один аргумент. Его также можно использовать с правой стороны фильтра или непосредственно в качестве аннотации.

bilateral

Логическое значение, указывающее, должно ли это преобразование применяться как к lhs, так и к rhs. Двусторонние преобразования будут применены к rhs в том же порядке, в котором они отображаются в поисковом выражении. По умолчанию установлено значение False. Для примера использования смотрите howto/custom-lookups.

lhs

Левая сторона - что трансформируется. Она должна следовать API запроса.

lookup_name

Имя поиска, используемое для его идентификации при разборе выражений запроса. Он не может содержать строку "__".

output_field

Определяет класс, который выводит это преобразование. Это должен быть экземпляр Field. По умолчанию совпадает с его lhs.output_field.

Справочник по Lookup

class Lookup[исходный код]

Lookup - это универсальный класс для реализации поиска. Поиск - это выражение запроса с левой стороны lhs; правой стороны rhs; и lookup_name, которое используется для получения логического сравнения между lhs и rhs, такого как lhs in rhs или lhs > rhs.

Основной нотацией для использования поиска в выражении является <lhs>__<lookup_name>=<rhs>. Поиск можно также использовать непосредственно в фильтрах QuerySet:

Book.objects.filter(LessThan(F("word_count"), 7500))

…или аннотации:

Book.objects.annotate(is_short_story=LessThan(F("word_count"), 7500))
lhs

Левая часть - то, что ищется. Объект обычно следует за Query Expression API. Это может быть и простое значение.

rhs

Правая часть - с чем сравнивается lhs. Это может быть простое значение или что-то, что компилируется в SQL, обычно это объект F() или QuerySet.

lookup_name

Имя этого поиска, используется для его идентификации при разборе выражений запроса. Он не может содержать строку "__".

prepare_rhs

По умолчанию имеет значение True. Когда rhs является простым значением, prepare_rhs определяет, следует ли его подготовить для использования в качестве параметра в запросе. Для этого вызывается lhs.output_field.get_prep_value(), если оно определено, или rhs оборачивается в Value() в противном случае.

process_lhs(compiler, connection, lhs=None)[исходный код]

Возвращает кортеж (lhs_string, lhs_params), как возвращено compiler.compile(lhs). Этот метод может быть переопределен для настройки обработки lhs.

compiler - это объект SQLCompiler, который используется как compiler.compile(lhs) для компиляции lhs. connection может использоваться для компиляции специфичного для поставщика SQL. Если lhs не None, используйте его как обработанный lhs вместо self.lhs.

process_rhs(compiler, connection)[исходный код]

Ведет себя так же, как process_lhs(), для правой части.

Вернуться на верх