Что такое queryset django

Django ORM и QuerySet

В этой главе ты узнаешь, как Django подключается к базе данных и сохраняет в неё информацию. Давай начнём!

Что такое QuerySet?

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

Проще научиться на примере. Давай попробуем, согласна?

Интерактивная консоль Django

Открой свой локальный терминал (не на PythonAnywhere) и набери следующую команду:

Результат должен быть таким:

Ты находишься в интерактивной консоли Django. По сути, это та же интерактивная консоль Python, но с магией Django 🙂 Ты можешь использовать весь синтаксис Python, разумеется.

Все объекты

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

Упс! Ошибка. Она говорит, что не существует объекта с именем Post. И это верно — мы забыли импортировать его!

Это список записей, с которыми мы работали до этого! Мы создали их через панель администратора Django. Теперь же мы хотим создавать записи с помощью Python, так как же мы этого добьёмся?

Создаём объект

Создать объект Post в базе данных можно следующим образом:

Давай для начала импортируем модель User:

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

Это суперпользователь, которого мы создали ранее! Нам нужен его экземпляр:

Как ты можешь заметить, мы получили ( get ) пользователя ( User ) с именем username ‘ola’. Шикарно! В твоём случае имя, конечно, может отличаться.

Теперь мы, наконец, можем создать наш пост:

Ура! Хочешь проверить, что всё работает?

Есть, ещё один пост в списке!

Добавляем записи

Можешь повеселиться и добавить ещё записей. 2-3 будет достаточно.

Фильтрация объектов

Ты также можешь получить список всех опубликованных записей. Мы просто отфильтруем записи по полю published_date :

К сожалению, пост, который мы добавили в консоли Python, ещё не опубликован. Мы можем изменить это! Сначала выберем запись, которую мы хотим опубликовать:

Теперь попробуй получить список опубликованных сообщений снова (нажми стрелку вверх 3 раза и затем enter ):

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

QuerySets позволяет сортировать объекты. Давай попробуем сортировку по полю created_date :

Соединение QuerySets

QuerySets можно сцеплять, создавая цепочки:

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

Отлично! Теперь ты готова к следующей части! Чтобы закрыть интерактивную консоль, набери:

Источник

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

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

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

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

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

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

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

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

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

Сериализация 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¶

В предыдущих версиях Django можно было использовать только функции агрегации. Теперь можно использовать любые типы выражений.

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

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

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

order_by¶

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

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

Была добавлена возможность использовать сортировку по внешнему ключу без использования JOIN

Вы можете также сортировать по выражению, вызвав asc() или desc() для выражения:

Была добавлена возможность сортировать по выражению.

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

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

Если вы не хотите использовать сортировку, даже указанную по-умолчанию, выполните метод 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 :

Вы можете использовать select_related() с любым “queryset”:

Порядок использования filter() и select_related() не важен. Эти экземпляры QuerySet одинаковы:

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

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

prefetch_related¶

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

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

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

Запрос для загрузки данных, указанных в 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¶

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

get_or_create¶

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

Этот метод удобно использовать для скриптов импорта данных. Например:

Такой способ становится весьма громоздким при увеличении количества полей модели. Пример выше может быть переписан с использованием метода get_or_create() :

Наконец, несколько слов об использовании get_or_create() в представлениях Django. Пожалуйста используйте его только для POST запросов, если только у вас нет основательных причин не делать этого. Запросы GET не должны влиять на данные; используйте запрос POST для изменения данных. Подробнее смотрите раздел о безопасных методах в спецификации HTTP.

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

Это произошло, потому что мы пытались получить или создать “Chapter 1” для книги “Ulysses”, но ни один объект не был найден, т.к. он не связан с этой книгой, и мы получили ошибку при попытке его создать т.к. поле title должно быть уникальным.

update_or_create¶

Удобный метод для обновления объекта по заданным параметрам поиска kwargs и создания нового при необходимости. defaults – словарь полей и значений для обновления объекта.

Этот метод удобно использовать для скриптов импорта данных. Например:

Такой способ становится весьма громоздким при увеличении количества полей модели. Пример выше может быть переписан с использованием метода update_or_create() :

bulk_create¶

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

Следует упомянуть ряд оговорок:

Метод модели save() не будет вызван, и сигналы pre_save и post_save не будут вызваны.

Не работает с дочерними моделями при multi-table наследовании.

Не работает со связями многое-ко-многим.

Параметр batch_size указывает количество объектов, которые будут созданы за один запрос. По умолчанию все объекты создаются одним запросом, кроме SQLite, где есть ограничение на количество переменных в запросе равное 999.

count¶

В зависимости от типа базы данных (например, PostgreSQL vs. MySQL), count() может вернуть long integer вместо обычно целого Python. Это особенности реализации, которые не должны создавать проблем.

in_bulk¶

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

При передаче в in_bulk() пустого списка будет получен пустой словарь.

iterator¶

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

latest¶

Этот пример возвращает последний объект Entry в таблице по полю pub_date :

Заметим что earliest() и latest() существует исключительно для удобства и читаемости.

earliest¶

first¶

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

first() создан просто для удобства и аналогичен следующему коду:

aggregate¶

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

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

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

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

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

exists¶

Самый эффективный способ определить принадлежит ли объект с уникальным полем (например, primary_key ) какому-либо QuerySet :

Что будет на много быстрее, чем получение и итерация по всему результату:

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

Это будет быстрее чем:

. но не на много(разве что результат содержит большое количество записей).

update¶

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

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

Вы можете изменить несколько полей — нет ограничения на количество полей. Например, изменим поля comments_on и headline :

Однако вы можете использовать фильтры по полям связанной модели:

Метод update() возвращает количество измененных записей:

delete¶

Например, удалим все записи для определенного блога:

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

Заметим, что запросы, созданные при удалении объектов не обсуждаются т.к. являются деталями реализации Django.

as_manager¶

Операторы фильтрации¶

Встроенные фильтры Django представлены ниже. Также можно создать собственный фильтр для поля модели.

exact¶

iexact¶

Регистронезависимое точное совпадение.

Используя SQLite и Unicode (не-ASCII) строки, помните замечание о сравнении строк в SQLite. SQLite не выполняет регистронезависимое сравнение Unicode строк.

contains¶

Регистрозависимая проверка на вхождение.

SQLite не поддерживает регистрозависимый оператор LIKE ; contains работает так же как и icontains для SQLite. Смотрите замечание о сравнении строк в SQLite.

Источник

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

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

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

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

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

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

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

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

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

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

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

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

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

You can’t share pickles between versions

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

QuerySet API¶

Обычно работа с 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 не содержит сортировки по-умолчанию.

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

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

reverse¶

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

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

distinct¶

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

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

Возможность указывать поля доступна только в PostgreSQL.

values¶

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

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

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

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

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

values_list¶

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

dates¶

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

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

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

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

Возвращает EmptyQuerySet — подкласс QuerySet который всегда возвращает пустой список. Полезен, если необходимо вернуть пустой результат, но код ожидает объект QuerySet (вместо того, что бы возвращать пустой список, например.)

select_related¶

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

И с select_related :

select_related() выбирает связанные объекты максимально доступной вложенности. Например, у нас есть такие модели:

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

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

В таком случае можно использовать аргумент depth при вызове select_related() контролируя глубину вложенности получения связанных объектов:

. и вам нужны только room и subject :

prefetch_related¶

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

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

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

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

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

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

Конечно, связь best_pizza может быть получена через select_related что бы уменьшить количество запросов до двух:

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

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

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

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

extra¶

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

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

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

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

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

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

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

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

defer¶

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

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

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

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

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

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

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

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

using¶

select_for_update¶

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

Следует отметить, что использование select_for_update() приводит к тому, что текущая транзакция считается “грязной” (если используется управление транзакциями). Это происходит, потому что Django блокирует указанные записи в БД и держит их до выполнения фиксации( COMMIT ) или отката( ROLLBACK ) произведённых изменений, освобождая поставленные ранее блокировки в базе данных.

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

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

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

create¶

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

get_or_create¶

Этот метод удобно использовать для скриптов импорта данных. Например:

Такой способ становится весьма громоздким при увеличении количества полей модели. Пример выше может быть переписан с использованием метода get_or_create() :

Наконец, несколько слов об использовании«get_or_create()« в представлениях Django. Как упоминалось выше, get_or_create() полезен в скриптах, которые парсят данные и создают новые объекты при необходимости. Но если вам нужно использовать get_or_create() в представлении, пожалуйста используйте его только для POST запросов, если только у вас нет основательных причин не делать этого. Запросы GET не должны влиять на данные; используйте запрос POST для изменения данных. Подробнее смотрите раздел о безопасных методах в спецификации HTTP.

bulk_create¶

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

Следует упомянуть ряд оговорок:

Метод модели save() не будет вызван, и сигналы pre_save и post_save не будут вызваны.

Не работает с дочерними моделями при multi-table наследовании.

В SQLite существует ограничение на количество параметров в SQL запросе. Максимальное количество определяется опцией SQLITE_MAX_VARIABLE_NUMBER при компиляции, которая по умолчанию равна 999. Например, модель содержит 8 полей (включая первичный ключ), вы не можете создать больше чем 999 // 8 = 124 объектов за раз. Если вы превысите этот лимит, будет вызвано исключение:

Если для производительности вашего приложения не хватает ограничения SQLite, вам следует использовать другую базу данных, например PostgreSQL.

count¶

В зависимости от типа базы данных (например, PostgreSQL vs. MySQL), count() может вернуть long integer вместо обычно целого Python. Это особенности реализации, которые не должны создавать проблем.

in_bulk¶

Получает список первичных ключей и возвращает словарь ассоциирующий объекты с передаными ID.

При передаче в in_bulk() пустого списка будет получен пустой словарь.

iterator¶

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

latest¶

Этот пример возвращает последний объект Entry в таблице по полю pub_date :

Заметим что latest() существует исключительно для удобства и читаемости.

aggregate¶

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

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

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

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

exists¶

update¶

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

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

Вы можете изменить несколько полей — нет ограничения на количество полей. Например, изменим поля comments_on и headline :

Однако вы можете использовать фильтры по полям связанной модели:

Метод update() возвращает количество измененных записей:

delete¶

Например, удалим все записи для определенного блога:

Операторы фильтрации¶

exact¶

iexact¶

Регистро-независимое точное совпадение.

Используя SQLite и Unicode (не-ASCII) строки, помните замечание о сравнении строк в SQLite. SQLite не выполняет регистро-независимое сравнение Unicode строк.

contains¶

Регистро-зависимая проверка на вхождение.

SQLite не поддерживает регистро-зависимый оператор LIKE ; contains работает так же как и icontains для SQLite. Смотрите замечание о сравнении строк в SQLite.

icontains¶

Регистро-независимая проверка на вхождение.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *