• 3.1
  • 3.2
  • 5.0
  • Версия документации: 6.1

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

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

API поиска состоит из двух компонентов: класс RegisterLookupMixin, который регистрирует поиск, и Query Expression 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, возвращая первое совпадение. Поиск экземпляров переопределит любой поиск классов с тем же именем_идентификатора.

get_lookups()

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

get_transform(transform_name)

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

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

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

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

as_sql(compiler, connection)

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

Вызов 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)

Должен вернуть поиск с именем «имя_искателя». Например, вернув 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.

Ссылка Преобразование

class Transform

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

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

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

bilateral

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

lhs

Левая часть – что трансформируется. Оно должно соответствовать Query Expression API.

lookup_name

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

output_field

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

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

class Lookup

«Lookup» — это универсальный класс для реализации поиска. Поиск — это выражение запроса с левой частью: lhs; правая часть: rhs; и ищу_имя, которое используется для создания логического сравнения между lhs и rhs, например, lhs в 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

Правая часть — с чем сравнивается «левая сторона». Это может быть простое значение или что-то, что компилируется в 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.

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

process_rhs(compiler, connection)

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

Back to Top