iexact django что это

Работа с запросами¶

В этом руководстве (и в справочнике) мы будем ссылаться на следующие модели, которые составляют приложение Weblog:

Создание объектов¶

Для представления данных таблицы базы данных в объектах Python Django использует интуитивно понятную систему: класс модели представляет таблицу базы данных, а экземпляр этого класса представляет конкретную запись в таблице базы данных.

Предполагая, что модели находятся в файле mysite/blog/models.py :

Метод save() не имеет возвращаемого значения.

save() использует несколько дополнительных параметров, которые здесь не описаны. Смотрите документацию save() для получения полной информации.

Сохранение изменений в объектах¶

Сохранение полей ForeignKey и ManyToManyField ¶

Джанго сообщит, если вы попытаетесь назначить или добавить объект неправильного типа.

Получение объектов¶

Чтобы получить объекты из вашей базы данных, создайте QuerySet через Manager в своем классе модели.

Managers доступны только через классы модели, а не из экземпляров модели, чтобы обеспечить разделение между операциями на уровне таблицы и операциями на уровне записи.

Получение всех объектов¶

Метод all() возвращает QuerySet всех объектов в базе данных.

Получение определенных объектов с помощью фильтров¶

Например, чтобы получить QuerySet записей блога за 2006 год, используйте filter() примерно так:

С классом менеджера по умолчанию, он такой же, как:

Цепочки фильтров¶

Отфильтрованные QuerySet являются уникальными¶

Получение одного объекта с помощью get() ¶

Если вы знаете, что только один объект соответствует вашему запросу, вы можете использовать метод get() из Manager который возвращает объект напрямую:

Другие методы QuerySet ¶

Ограничение QuerySet ¶

Например, этот код возвращает первые 5 объектов ( LIMIT 5 ):

Это возвращает объекты с шестого по десятый ( OFFSET 5 LIMIT 5 ):

Отрицательное индексирование (т.е. Entry.objects.all()[-1] ) не поддерживается.

Дальнейшая фильтрация или упорядочение нарезанного набора запросов запрещены из-за неоднозначного характера того, как это может работать.

Чтобы извлечь один объект, а не список (например, SELECT foo FROM bar LIMIT 1 ), используйте простой индекс вместо среза. Например, этот код возвращает первый Entry в базе данных, после упорядочивания записей в алфавитном порядке по заголовку:

Это примерно эквивалентно:

Поиск по полям¶

переводит (примерно) в следующий SQL:

Python имеет возможность определять функции, которые принимают произвольные аргументы имя-значение, имена и значения которых оцениваются во время выполнения. Для получения дополнительной информации см. Keyword Arguments в официальном руководстве по Python.

«Точное» совпадение. Например:

Будет генерировать SQL по этим строкам:

Например, следующие два оператора эквивалентны:

Это сделано для удобства, потому что точный поиск является распространенным случаем.

Соответствие без учета регистра. Итак, запрос:

Проверка содержимого в зависимости от регистра. Например:

Примерно переводится в такой SQL:

Поиск, который использует отношения¶

Django предлагает мощный и интуитивно понятный способ «отслеживать» отношения в поисках, автоматически заботясь о SQL JOIN для вас, за кулисами. Чтобы охватить отношение, просто используйте имя поля связанных полей в моделях, разделенных двойным подчеркиванием, пока не дойдете до нужного поля.

Этот охват может быть настолько глубоким, насколько вы захотите.

Если вы фильтруете по нескольким отношениям и одна из промежуточных моделей не имеет значения, которое удовлетворяет условию фильтра, Django будет обрабатывать его как пустой (все значения NULL ), но допустимый объект там. Все это означает, что никакой ошибки не возникнет. Например, в этом фильтре:

Охватывающие многозначные отношения¶

Это может показаться немного запутанным, поэтому, надеемся, пример прояснит. Чтобы выбрать все блоги, которые содержат записи с «Lennon» в заголовке и которые были опубликованы в 2008 году (та же запись, удовлетворяющая обоим условиям), мы должны написать:

Чтобы выбрать все блоги, которые содержат запись с «Lennon» в заголовке, а также запись, которая была опубликована в 2008 году, мы должны написать:

Предположим, что существует только один блог, в котором есть записи, содержащие «Lennon» и записи 2008 года, но ни одна из записей 2008 года не содержит «Lennon». Первый запрос не вернет ни одного блога, но второй запрос вернет этот блог.

Например, следующий запрос исключит блоги, содержащие обе записи с «Lennon» в заголовке и записи, опубликованные в 2008 году:

Фильтры могут ссылаться на поля модели¶

В приведенных выше примерах мы создали фильтры, которые сравнивают значение модельного поля с константой. Но что, если вы хотите сравнить значение поля модели с другим полем той же модели?

Например, чтобы найти список всех записей блога, у которых было больше комментариев, чем у пингбэков, мы создаем объект F() для ссылки на счетчик пингбэков и используем этот объект F() в запросе:

Чтобы найти все записи, в которых рейтинг записи меньше суммы пингбэков и комментариев, мы должны выполнить запрос:

Oracle не поддерживает побитовую операцию XOR.

Использование сокращения pk ¶

Поиск pk также работает через объединения. Например, эти три утверждения эквивалентны:

Экранирующие знаки процента и подчеркивания в выражениях LIKE ¶

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

Джанго заботится об экранировании для вас; результирующий SQL будет выглядеть примерно так:

То же самое касается подчеркивания. Оба знака процента и подчеркивания обрабатываются для вас прозрачно.

Кэширование и QuerySet ¶

Каждый класс QuerySet содержит кэш для минимизации доступа к базе данных. Понимание того, как это работает, позволит вам написать наиболее эффективный код.

Это означает, что один и тот же запрос к базе данных будет выполнен дважды, что фактически удваивает нагрузку на вашу базу данных. Кроме того, существует вероятность того, что два списка могут не включать в себя одни и те же записи базы данных, потому что «запись» может быть добавлена или удалена за доли секунды между двумя запросами.

Чтобы избежать этой проблемы, просто сохраните QuerySet и повторно используйте его:

Когда QuerySet не кэшируется¶

Queryset`ы не всегда кэшируют свои результаты. При оценке только части набора запросов проверяется кэш, но если он не заполняется, элементы, возвращаемые последующим запросом, не кэшируются. В частности, это означает, что ограничение набора запросов с использованием среза массива или индекса не заполнит кэш.

Читайте также:  при какой температуре происходит брожение вина в домашних условиях

Например, многократное получение определенного индекса в объекте набора запросов будет каждый раз запрашивать базу данных:

Однако, если весь набор запросов уже был оценен, вместо этого будет проверяться кеш:

Вот несколько примеров других действий, которые приведут к оценке всего набора запросов и, следовательно, заполнению кеша:

Простой вывод набора запросов не заполнит кэш. Это связано с тем, что вызов __repr__() возвращает только часть всего набора запросов.

Запросы к JSONField ¶

Хранение и запрос для « None«¶

Преобразование ключа, индекса и пути¶

Для запроса на основе заданного ключа словаря используйте этот ключ в качестве имени поиска:

Несколько ключей могут быть объединены в цепочку для формирования пути поиска:

Если ключ является целым числом, он будет интерпретирован как преобразование индекса в массиве:

Чтобы запросить отсутствующие ключи, используйте поиск isnull :

Поскольку любая строка может быть ключом в объекте JSON, любой поиск, кроме перечисленных ниже, будет интерпретироваться как поиск ключа. Ошибок не возникает. Будьте особенно осторожны с опечатками и всегда проверяйте, работают ли ваши запросы так, как вы хотите.

Пользователи MariaDB и Oracle

Использование order_by() для преобразований ключа, индекса или пути отсортирует объекты с использованием строкового представления значений. Это связано с тем, что MariaDB и Oracle Database не предоставляют функцию, которая преобразует значения JSON в их эквивалентные значения SQL.

Сдерживание и ключевые поиски¶

contains ¶

contains не поддерживается в Oracle и SQLite.

contained_by ¶

contains_by не поддерживается в Oracle и SQLite.

has_key ¶

Возвращает объекты, в которых данный ключ находится на верхнем уровне данных. Например:

has_keys ¶

Возвращает объекты, в которых все данные ключи находятся на верхнем уровне данных. Например:

has_any_keys ¶

Возвращает объекты, где любой из указанных ключей находится на верхнем уровне данных. Например:

Сложные поиски с объектами Q ¶

Например, этот объект Q инкапсулирует один запрос LIKE :

Это эквивалентно следующему оператору SQL WHERE :

Вы можете составлять операторы произвольной сложности, комбинируя объекты Q с операторами & и | и используя группировку в скобках. Кроме того, объекты Q могут быть отменены с помощью оператора

, что позволяет комбинировать поиск, который объединяет как обычный запрос, так и отрицательный ( NOT ) запрос:

… примерно переводится в SQL как:

… будет правильным запросом, эквивалентным предыдущему примеру, но:

Сравнение объектов¶

Удаление объектов¶

Например, это удаляет все объекты Entry с pub_date 2005 года:

Копирование экземпляров модели¶

Все становится сложнее, если вы используете наследование. Рассмотрим подкласс Blog :

Из-за того, как работает наследование, вы должны установить для pk и id значение None :

Для OneToOneField вы должны продублировать связанный объект и назначить его полю нового объекта, чтобы избежать нарушения однозначного уникального ограничения. Например, предполагая, что entry уже продублировано, как указано выше:

Обновление нескольких объектов одновременно¶

Метод update() применяется мгновенно и возвращает количество строк, соответствующих запросу (которое может быть не равно количеству обновленных строк, если некоторые строки уже имеют новое значение). Единственное ограничение на обновляемый QuerySet состоит в том, что он может получить доступ только к одной таблице базы данных: главной таблице модели. Вы можете фильтровать на основе связанных полей, но вы можете обновить только столбцы в основной таблице модели. Пример:

Вызовы обновлений также могут использовать выражения F для обновления одного поля на основе значения другого поля в модели. Это особенно полезно для увеличения счетчиков на основе их текущего значения. Например, чтобы увеличить количество пингбэков для каждой записи в блоге:

Связанные объекты¶

(За кулисами эта функциональность реализована с помощью дескрипторов Python. Это не должно иметь большого значения для вас, но мы отметим это здесь для любопытных.)

Отношения один ко многим¶

Прямые¶

Если поле ForeignKey установлено null=True (т.е. оно допускает значения NULL ), вы можете назначить None для удаления отношения. Пример:

Прямой доступ к отношениям «один ко многим» кэшируется при первом обращении к связанному объекту. Последующие обращения к внешнему ключу в том же экземпляре объекта кэшируются. Пример:

Обратные отношения¶

Использование собственного реверсивного менеджера¶

Указание собственного обратного менеджера также позволяет вам вызывать его пользовательские методы:

Дополнительные методы для обработки связанных объектов¶

Чтобы назначить членов связанного набора, используйте метод set() с повторяющимися экземплярами объекта. Например, если e1 и e2 являются экземпляром Entry :

Каждая «обратная» операция, описанная в этом разделе, оказывает непосредственное влияние на базу данных. Каждое добавление, создание и удаление немедленно и автоматически сохраняется в базе данных.

Отношения многие ко многим¶

Обе стороны отношения «многие ко многим» получают автоматический доступ API другой стороны. API работает аналогично «обратному» отношению «один ко многим» выше.

Пример облегчает понимание:

Отношения один-к-одному¶

Отношения один-к-одному очень похожи на отношения многие-к-одному. Если вы определяете OneToOneField в вашей модели, экземпляры этой модели будут иметь доступ к связанному объекту через простой атрибут модели.

Экземпляры могут быть назначены на обратную связь так же, как вы бы назначили прямую связь:

Как возможны обратные отношения?¶

Другие объектно-реляционные связи требуют, чтобы вы определяли отношения с обеих сторон. Разработчики Django считают, что это является нарушением принципа DRY (не повторяй себя), поэтому Django требует, чтобы вы определяли отношения только с одной стороны.

Но как это возможно, учитывая, что класс модели не знает, какие другие классы модели связаны с ним, пока эти другие классы модели не будут загружены?

Запросы к связанным объектам¶

Запросы, связанные со связанными объектами, подчиняются тем же правилам, что и запросы, включающие поля с обычными значениями. При указании значения для сопоставляемого запроса вы можете использовать либо сам экземпляр объекта, либо значение первичного ключа для объекта.

Читайте также:  какой наждачкой полировать машину после покраски

Откат к сырому SQL¶

Источник

Документация Django 1.7

Этот раздел описывает QuerySet API. Изложенный материал опирается на материал, изложенный в разделах о моделях и выполнении запросов, возможно вам следует прочитать их перед прочтением этого раздела.

В примерах будут использованы :ref:` примеры моделей web-блога ` представленные в разделе о выполнении запросов.

Когда вычисляется QuerySets¶

QuerySet может быть создан, отфильтрован, ограничен и использован фактически без выполнения запросов к базе данных. База данных не будет затронута, пока вы не спровоцируете выполнение QuerySet.

QuerySet будет вычислен при таких действиях:

Итерация. QuerySet – это итератор, и при первом выполнении итерации будет произведен запрос к базе данных. Например, этот код выводи заголовки статей из базы данных:

Pickling/кэширование. Смотрите соответствующий раздел о pickling QuerySets. Основное замечание это то, что при этих операциях будет выполнен запрос к базе данных.

len(). QuerySet будет вычислен при выполнении len() над ним. Как вы и ожидаете будет возвращено количество объектов в результате выборки.

list(). QuerySet будет вычислен при использовании list() над ним. Например:

Заметка: не используйте такой подходи, если необходимо всего лишь узнать содержит ли результат запроса хотя бы один объект, и вам не нужен сам результат. Эффективнее использовать метод exists() (смотрите ниже).

Сериализация QuerySets¶

Атрибут query не является частью публичного API, и является частью внутреннего механизма создания запросов. Однако, поддерживает использование pickle и unpickle как показано в примере выше.

нельзя переносить “pickles” между версиями

Сериализация QuerySets возможна только для версии Django, которая была использована при сохранении объекта. При сериализации объекта в версии Django N, нет гарантии что, его можно будет восстановить в версии Django N+1. Сериализация не должна быть использована для долговременного хранения данных.

QuerySet API¶

Вот документированное объявление QuerySet :

Обычно работа с QuerySet состоит в использовании цепочек фильтров. Для этого большинство методов QuerySet возвращает новый “queryset”. Эти методы описаны далее.

Класс QuerySet имеет два публичных атрибута:

База данных, которая будет использована для выполнения запроса.

Методы, которые возвращают новый QuerySets¶

filter¶

Возвращает новый QuerySet содержащий объекты отвечающие параметрам фильтрации.

exclude¶

Возвращает новый QuerySet содержащий объекты не отвечающие параметрам фильтрации.

Этот пример исключает все записи с pub_date раньше 3.01.2005 И с headline равным “Hello”:

Это эквивалентно запросу SQL:

Этот пример исключает все записи с pub_date раньше 3.01.2005 ИЛИ с headline равным “Hello”:

Это эквивалентно запросу SQL:

Обратите внимание на второй пример, который больше ограничивает выборку.

annotate¶

Аннотация определенная именованными аргументами будет использовать имя аргумента как название аннотации. Для позиционного аргумента будет использовано имя созданное с названия функции агрегации и используемого поля модели.

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

Для углубленного изучения агрегации смотрите раздел про агрегацию.

order_by¶

Заметка: запрос с order_by(‘?’) может быть медленным и сильно нагружать базу данных, зависит от типа базы данных, которую вы используете.

Для сортировки по полю из другой модели, используйте синтаксис аналогичный тому, который используется при фильтрации по полям связанной модели. То есть, название поля, далее два нижних подчеркивания ( __ ), и имя поля в новой модели, и так далее. Например:

. т.к. модель Blog не содержит сортировки по-умолчанию.

Обратите внимание, можно использовать сортировку по внешнему ключу без использования JOIN :

Нет способа указать должна ли сортировка учитывать регистр. По этому Django возвращает результат в таком порядке, в каком его вернула используемая база данных.

Если вы не хотите использовать сортировку, даже указанную по-умолчанию, выполните метод order_by() без аргументов.

Сортировка не бесплатная операция. Каждое поле влияет на скорость выполнения запроса. Каждый внешний ключ добавит сортировку по умолчанию связанной модели.

reverse¶

Чтобы получить “последние” пять объектов выполните:

distinct¶

Возвращает QuerySet с добавленным SELECT DISTINCT в SQL запрос. Повторяющиеся записи будут исключены из результатов запроса.

Примеры (все, кроме первого, будут работать только в PostgreSQL):

values¶

Каждый словарь представляет объект, ключи которого соответствуют полям модели.

Этот пример показывает разницу между результатом возвращаемым values() и объектами модели:

Следует упомянуть несколько тонкостей:

Было добавлено поведение из последнего пункта. Ранее вызов only() или defer() после values() был разрешен, но он приводил к ошибке или возвращал не верный результат.

ValuesQuerySet полезен, если вам нужны только данные некоторых полей и не нужен функционал объектов моделей. Более эффективно получить только необходимые данные.

Разработчики Django предпочитают использовать в первую очередь методы влияющие на SQL-запрос, далее методы влияющие на вывод данных (такие как values() ), хотя это и не имеет значения. Это ваш шанс проявить индивидуальность.

values_list¶

Если вы указали больше одного поля, использование flat будет ошибкой.

dates¶

«year» возвращает список уникальных значений года из всех дат указанного поля.

«month» возвращает список уникальных значений года/месяца из всех дат указанного поля.

«day» возвращает список уникальных значений года/месяца/дня из всех дат указанного поля.

datetimes¶

SQLite: установите pytz — преобразование выполняется в Python.

PostgreSQL: нет дополнительных требований (смотрите Time Zones).

Oracle: нет дополнительных требований (смотрите Choosing a Time Zone File).

MySQL: установите pytz и загрузите таблицы часовых поясов с помощью mysql_tzinfo_to_sql.

select_related¶

Возвращает QuerySet который автоматически включает в выборку данные связанных объектов при выполнении запроса. Повышает производительность, т.к. при доступе к связанным объектам через модель не потребуются дополнительные запросы в базу данных.

И с select_related :

Можно указывать поля связанных моделей как и при запросе. Например, у нас есть такие модели:

. тогда вызов Book.objects.select_related(‘person__city’).get(id=4) получит данные связанных Person и связанных City :

prefetch_related¶

Например, у вас есть две модели:

и выполняется такой код:

Мы можем уменьшить количество запросов до двух используя prefetch_related :

В этом случае self.toppings.all() подгружается для каждого объекта Pizza и при вызове self.toppings.all() будут использоваться подгруженные данные, вместо запроса к БД.

Читайте также:  что такое готовое блюдо

Запрос для загрузки данных указанных в prefetch_related() будет выполнен после выполнения основного запроса.

Помните, для всех QuerySets любой последующий метод, который изменяет запрос, проигнорирует ранее загруженный кэш и получит данные выполнив новый запрос. Итак, используя такой код:

Вы можете использовать стандартный синтаксис для обращения к связанным моделям. Например, добавим еще одну модель в пример выше:

Можно использовать такой запрос:

Это вернет “best pizza” и все “toppings” для них для каждого ресторана. Будет выполнено 3 запроса.

Так как предварительная загрузка выполняется после основного запроса (который включает все необходимые объединения таблиц для обработки select_related ), она способна определить что объекты best_pizza уже получены и не выполнит их загрузку снова.

Использование нескольких вызовов prefetch_related соберет вместе все предварительно загружаемые поля. Чтобы их обнулить, вызовите метод prefetch_related с аргументом None :

prefetch_related в основном использует оператор ‘IN’ SQL запроса. Это означает, что для больших QuerySet может быть создано сложное условие ‘IN’, что, в зависимости от базы данных, может привести к проблемам с производительностью при разборе и выполнении SQL запроса. Всегда анализируйте(profile) ваш запрос!

Заметим, если вы используете iterator() для выполнения запроса, вызов prefetch_related() будет проигнорирован т.к. использование этих двух оптимизаций вместе не имеет смысла.

В самом простом варианте Prefetch аналогичен обычному строковому аргументу:

Результат с собственным to_attr может использоваться в аргументах запроса:

Использование to_attr рекомендуется при фильтрации результата предварительной загрузки т.к. это менее двусмысленно, чем сохранение результата фильтрации в кэше связывающего менеджера:

Вы хотите загрузить только часть связанных объектов.

Вы хотите оптимизировать запрос, отфильтровав часть полей :

Порядок аргументов имеет значение.

Возьмем следующие примеры:

В это примере ‘pizzas__toppings’ уже получает всю необходимую информацию, поэтому ‘pizzas’ лишний. (FIXME)

extra¶

По определению, дополнительные параметры поиска определенные в extra() не переносимы между различными типами данных(потому что вы используете непосредственно SQL) и нарушает принцип DRY, по этому вы должны избегать использование этого метода.

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

Заметим, что скобки вокруг подзапроса, обязательные для некоторых баз данных, не обязательны для параметра select в Django. Также заметим, что некоторые типы баз данных, такие как некоторые версии MySQL, не поддерживают подзапросы.

. будет переведено (примерно) в следующий SQL:

Будьте внимательны при добавлении в параметр tables таблиц, которые уже используются запросом. В таком случае Django предполагает, что вы хотите добавить их повторно. Это создает проблему, т.к. таблица будет добавлена с псевдонимом(an alias). Если таблица несколько раз используется в запросе, второй и последующие вхождения должны использовать псевдонимы, чтобы база данных могла различить их. При обращении к добавленной таблице в параметре where вы получите ошибку.

Скорее всего вы будете использовать дополнительные таблицы, которые еще не добавлены в запрос. Однако, если все таки возникнет описанная выше ситуация, существует несколько способов ее решить. Первый, посмотрите возможно ли использовать уже добавленную в запрос таблицу. Если это не возможно, используйте вызов extra() в начале конструкции запроса, чтобы ваша таблица использовалась первой. В конце концов, если каким-то образом все остальное вам не помогло, посмотрите на созданный запрос и перепишите параметр where таким образом, чтобы использовался псевдоним назначенный дополнительной таблице. При одинаковом способе создать запрос псевдоним будет всегда не измененным.

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

Всегда используйте params вместо добавления значений непосредственно в where т.к. params гарантирует, что все значения будут экранированы в соответствиями с синтаксисом используемой базы данных. Например, кавычки будут экранированы правильно.

defer¶

При сложной структуре данных модели могут содержать большое количество полей, некоторые из которых могут содержать большие объемы данных(например, текстовые поля), или использовать ресурсоемкий процесс преобразования данных в объекты Python. Если вы точно знаете, что данные этих полей не будут использоваться при работе с результатами запроса, вы можете указать Django не выбирать эти поля из базы данных.

Это делается передачей названия полей, которые не должны быть загружены, в метод defer() :

Результат все также будет содержать объекты модели. Каждое не выбранное поле будет получено из базы данных при обращении к нему (одна за раз, не все “отложенные” поля сразу).

Порядок добавления полей не имеет значения. Вызов defer() с полем, которое уже было добавлено в список “отложенных”, ничего не изменит (поле все также не будет выбираться из базы данных).

Вы можете указать поля связанных моделей (если эти модели загружаются через select_related() ) используя стандартный синтаксис двух нижних подчеркиваний для разделения полей:

Если вы хотите очистить список “отложенных” полей, передайте None как параметр для defer() :

Метод defer() (и его “коллега” only() ) предназначены только для опытных пользователей. Они предоставляют возможность оптимизировать запрос. Но для начала вам следует проанализировать его, точно определить какие данные вам необходимы и удостовериться, что разница между получением всех полей и получением определенных, будет значительной.

При вызове only() будет заменено множество загружаемых полей. Название метода говорит само за себя: только эти поля должны быть загружены; все остальные – “отложены”. Таким образом при последовательном вызове only() несколько раз, только поля из последнего вызова будут загружены:

using¶

select_for_update¶

Все, удовлетворяющие фильтрам, строки будут заблокированы до завершения транзакции, то есть другие транзакции не смогут изменить или заблокировать это строки.

Использовании select_for_update() в autocommit режиме теперь вызывает исключение.

Методы, которые не возвращают QuerySets¶

Эти методы не используют кэш (смотрите Кэширование и QuerySets) и выполняют запрос к базе данных при каждом вызове.

Возвращает объект соответствующий параметрам поиска, которые должны быть указанны в формате описанном в разделе о параметрах поиска

create¶

Удобный метод создать и сохранить объект. Таким образом:

Источник

Сказочный портал