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

В этом документе подробно описывается API объектов QuerySet . Он дополняет содержимое, представленное в руководствах по моделям и запросах к базе данных , поэтому рекомендуется прочитать и понять их, прежде чем читать это.

В этом справочнике мы будем использовать образцы шаблонов веб-журнала, показанные в Руководстве по запросам базы данных .

Когда QuerySet оцениваются объекты

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

Один QuerySet оценивается в следующих контекстах:

  • Итерация. Один QuerySet является повторяемым, и он выполняет свой запрос к базе данных на первой итерации. Например, здесь отображаются заголовки всех статей в базе данных:

    for e in Entry.objects.all():
        print(e.headline)
    

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

  • Сегментация. Как объясняется в разделе Ограничение QuerySets , QuerySet можно сегментировать с помощью синтаксиса сегментации списка Python. Сегментирование неоцененного QuerySet объекта обычно возвращает другой QuerySet неоцененный объект , но Django выполняет запрос к базе данных, если вы используете параметр step синтаксиса сегментации, и в этом случае возвращается список. Сегментация одного QuerySet из прошедших оценку также возвращает список.

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

  • «Травление» / кеширование. См. Следующий раздел для получения дополнительных сведений о последствиях «выбора» объектов QuerySets . С точки зрения этого раздела важно то, что результаты считываются из базы данных.

  • repr (). A QuerySet оценивается, когда он включен в вызов repr() . Это сделано для удобства в интерактивном интерпретаторе Python, чтобы сразу визуализировать результаты с помощью API в интерактивном режиме.

  • len (). A QuerySet оценивается, когда он включен в вызов len() . Это возвращает ожидаемую длину результирующего списка.

    Примечание: если вам нужно знать только количество записей в результате (и вам не нужны сами объекты), гораздо эффективнее обрабатывать публикацию на уровне базы данных, используя код SQL . Django предоставляет метод именно по этой причине.SELECT COUNT(*) count()

  • список (). Принудительно оценивает a QuerySet при включении в вызов list() . Например :

    entry_list = list(Entry.objects.all())
    
  • bool (). Испытание QuerySet в логическом контексте, например, с помощью bool() , or , and или if , вызовет выполнение запроса. Если есть хотя бы один результат, QuerySet вернет его True , иначе False . Например :

    if Entry.objects.filter(headline="Test"):
       print("There is at least one Entry with the headline Test")
    

    Примечание: если все, что вас интересует, - это определить, есть ли хотя бы один результат (и вам не нужны сами объекты), его использовать более эффективно exists() .

QuerySet и «маринование»

Если вы трансформируете QuerySet пар pickle , все результаты будут загружены в память перед процессом травления. Обычно это предшествует кэшированию, и когда набор запросов извлекается из кеша, желательно, чтобы результаты были доступны и готовы к использованию (чтение из базы данных может занять много времени, что переопределит 'преимущество кеша). Это означает, что когда объект QuerySet реконструируется из его «рассоленного» представления, он содержит результаты того, когда он был преобразован с помощью «pickle», а не результаты текущего момента в базе данных.

Если вы не хотите, чтобы «рассол» информации , чтобы воссоздать его QuerySet из базы данных , когда это необходимо, предоставить замариновать атрибут query из QuerySet . Затем вы можете воссоздать QuerySet оригинал (без загрузки результатов), написав код, подобный этому:

>>> import pickle
>>> query = pickle.loads(s)     # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query            # Restore the original 'query'.

Атрибут query - непрозрачный объект. Это внутреннее представление конструкции запроса и не является частью общедоступного API. Однако сериализация и «рассредоточенная» десериализация содержимого этого атрибута - безопасная (и полностью приемлемая) операция.

Невозможно разделить сериализацию "pickle" между разными версиями.

Сериализации Pickle QuerySets действительны только для той версии Django, которая использовалась для их создания. Если вы создаете консервированный контент с помощью N-версии Django, нет гарантии, что это содержимое будет доступно для чтения N + 1-версией Django. Сериализация Pickle не должна использоваться как часть долгосрочной стратегии архивирования.

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

API QuerySet

Вот официальное заявление одного из них QuerySet :

classQuerySet ( model = None , query = None , using = None , hints = None )

Обычно, когда мы манипулируем одним QuerySet , мы делаем это путем объединения фильтров . Для этого большинство методов QuerySet возвращают новые объекты QuerySet . Эти методы подробно описаны ниже в этом разделе.

У класса QuerySet есть два общедоступных атрибута, которые можно использовать для интроспекции:

ordered

True если QuerySet сортируется, то есть имеет предложение по order_by() умолчанию или сортировку на уровне модели. В противном случае значение равно False .

db

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

Заметка

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

Способы возврата новых QuerySet

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

filter()

filter( ** kwargs )

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

Параметры поиска ( **kwargs ) должны быть в формате, описанном ниже в разделе « Поиск по полю» . Несколько параметров объединяются AND в базовом операторе SQL.

Если вам нужно выполнить более сложные запросы (например, запросы, содержащие операторы с OR (ИЛИ)), вы можете использовать .objets Q

exclude()

exclude( ** kwargs )

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

Параметры поиска ( **kwargs ) должны быть в формате, описанном ниже в разделе « Поиск по полю» . Несколько параметров объединяются AND в базовом операторе SQL, и все это объединяется в один NOT() .

В этом примере исключаются все элементы, pub_date выпущенные позже 2005-1-3 И headline содержащие "Hello":

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')

В терминах SQL это дает:

SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')

В этом примере исключаются все элементы, pub_date выпущенные позднее 2005-1-3 ИЛИ headline содержащие "Hello"

Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')

В терминах SQL это дает:

SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'

Обратите внимание, что второй пример более строгий.

Если вам нужно выполнить более сложные запросы (например, запросы, содержащие операторы с OR (ИЛИ)), вы можете использовать .objets Q

annotate()

annotate( * аргументы , ** kwargs )

Аннотирует каждый объект в QuerySet предоставленном списке выражений запроса . Выражение может быть одним значением, ссылкой на поле в модели (или любой связанной модели) или выражением агрегирования (средние, суммы и т. Д.), Которое было вычислено для объектов в связи с объектами в QuerySet .

Каждый параметр annotate() - это аннотация, которая будет добавлена ​​к каждому QuerySet возвращаемому объекту .

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

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

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

>>> from django.db.models import Count
>>> q = Blog.objects.annotate(Count('entry'))
# The name of the first blog
>>> q[0].name
'Blogasaurus'
# The number of entries on the first blog
>>> q[0].entry__count
42

Модель Blog не определяет атрибут entry__count сама по себе, но, используя именованный параметр для определения агрегатной функции, вы можете управлять именем аннотации:

>>> q = Blog.objects.annotate(number_of_entries=Count('entry'))
# The number of entries on the first blog, using the name provided
>>> q[0].number_of_entries
42

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

order_by()

order_by( * поля )

По умолчанию результаты, возвращаемые a QuerySet , сортируются в соответствии с кортежем сортировки, определенным параметром ordering класса Meta модели. Вы можете переопределить это для каждого QuerySet с помощью метода order_by .

Пример:

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')

Вышеупомянутые результаты будут отсортированы pub_date в обратном хронологическом порядке, а затем headline в алфавитном порядке. Знак минус спереди "-pub_date" указывает на инверсию порядка сортировки. Для случайной сортировки используйте "?" вот так:

Entry.objects.order_by('?')

Примечание. Запросы order_by('?') могут быть дорогими и медленными в зависимости от используемого ядра базы данных.

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

Entry.objects.order_by('blog__name', 'headline')

Если вы попытаетесь выполнить сортировку по полю, которое связано с другой моделью, Django использует сортировку по умолчанию связанной модели или сортирует по первичному ключу связанной модели, если атрибуты Meta.ordering отсутствуют. Например, поскольку в модели Blog нет порядка сортировки по умолчанию:

Entry.objects.order_by('blog')

… Идентичен:

Entry.objects.order_by('blog__id')

Если Blog включен , то первый набор запросов будет таким же, как:ordering = ['name']

Entry.objects.order_by('blog__name')

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

Entry.objects.order_by(Coalesce('summary', 'headline').desc())

asc() и desc() имеют параметры ( nulls_first и nulls_last ), управляющие сортировкой нулевых значений.

Будьте осторожны при сортировке по связанным полям модели, а также при использовании distinct() . См. Примечание в distinct() для объяснения возможного влияния сортировки по связанным шаблонам на ожидаемые результаты.

Заметка

Допускается определение многозначного поля как критерия сортировки (например, поле ManyToManyField или обратная связь поля ForeignKey ).

Рассмотрим этот случай:

class Event(Model):
   parent = models.ForeignKey(
       'self',
       on_delete=models.CASCADE,
       related_name='children',
   )
   date = models.DateField()

Event.objects.order_by('children__date')

В этом случае возможно, что для каждого существует несколько данных сортировки Event . Один Event со многими children будет возвращен несколько раз в новом, QuerySet созданном order_by() . Другими словами, нанесение order_by() на QuerySet может возвращать больше элементов , чем первоначальный набор, который не является ни ожидаемый результат , ни полезным.

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

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

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

Entry.objects.order_by(Lower('headline').desc())

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

Вы можете определить, отсортирован запрос или нет, запросив атрибут QuerySet.ordered , True когда QuerySet он был отсортирован каким-либо образом.

Каждый вызов order_by() стирает любой существующий ранее порядок сортировки. Например, этот запрос будет отсортирован по, pub_date а не по headline :

Entry.objects.order_by('headline').order_by('pub_date')

Предупреждение

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

Если запрос не имеет порядка сортировки, результаты возвращаются из базы данных в неопределенном порядке. Определенный порядок может быть гарантирован только в том случае, если порядок основан на одном или нескольких полях, которые однозначно идентифицируют каждый объект результата. Например, если поле nom не уникально, сортировка по этому полю не гарантирует, что объекты с одинаковым именем всегда будут отображаться в одном и том же порядке.

reverse()

reverse()

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

Чтобы получить «последние пять» элементов набора запросов, вы можете написать следующее:

my_queryset.reverse()[:5]

Обратите внимание, что это не совсем то же самое, что сегментирование от конца списка в Python. В приведенном выше примере сначала возвращается последний элемент, затем предпоследний и так далее. Если бы у нас был список Python и list[-5:] мы бы применили его, мы получили бы последние 5 элементов. Django не поддерживает этот режим доступа с наборами запросов (сегментация с конца), так как это невозможно сделать эффективно в SQL.

Также обратите внимание, что reverse() обычно следует вызывать только тот, QuerySet чей порядок сортировки определен (например, при запросе модели, определяющей сортировку или вызов по умолчанию order_by() ). Если данные QuerySet не включают порядок сортировки, вызов reverse() этого объекта не имеет реального эффекта (сортировка не была определена до вызова reverse() , она не будет определена впоследствии).

distinct()

distinct( * поля )

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

По умолчанию QuerySet повторяющиеся строки не удаляются. На практике это редко является проблемой, потому что простые запросы, такие как Blog.objects.all() не создают возможности дублирования строк результатов. Однако, если запрос охватывает несколько таблиц, можно получить повторяющиеся результаты при оценке QuerySet . Вот тогда и distinct() пригодится.

Заметка

Любое поле, упомянутое в вызове order_by() , включается в столбцы SELECT оператора SQL. Иногда это может привести к неожиданным результатам при использовании вместе с distinct() . Если вы сортируете в соответствии с полями из связанной модели, эти поля будут добавлены к выбранным столбцам, а определенные строки, которые обычно дублируются (следовательно, удаляются), затем отображаются как отдельные. Поскольку эти дополнительные столбцы не отображаются в возвращаемых результатах (они используются только для сортировки), может показаться, что в любом случае возвращаются повторяющиеся неотличимые строки.

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

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

Только в PostgreSQL вы можете передавать позиционные параметры ( *fields ), чтобы указать имена полей, к которым DISTINCT применяется оператор . Это создает такой SQL-запрос . Вот в чем разница. При обычном вызове база данных сравнивает каждое поле в каждой строке, чтобы определить, какие строки отличаются. При вызове с указанием имен полей база данных сравнивает только указанные поля для определения отдельных строк.SELECT DISTINCT ON distinct() distinct()

Заметка

При указании имен полей необходимо предоставить предложение order_by() для QuerySet , а поля в order_by() должны начинаться с полей из distinct() в том же порядке.

Например, возвращает первую строку для каждого значения в столбце . Если вы не укажете сортировку, выбор возвращаемой строки будет произвольным.SELECT DISTINCT ON (a) a

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

>>> Author.objects.distinct()
[...]

>>> Entry.objects.order_by('pub_date').distinct('pub_date')
[...]

>>> Entry.objects.order_by('blog').distinct('blog')
[...]

>>> Entry.objects.order_by('author', 'pub_date').distinct('author', 'pub_date')
[...]

>>> Entry.objects.order_by('blog__name', 'mod_date').distinct('blog__name', 'mod_date')
[...]

>>> Entry.objects.order_by('author', 'pub_date').distinct('author')
[...]

Заметка

Помните, что используются order_by() любые порядки сортировки по умолчанию, определенные для связанных моделей. Может потребоваться явная сортировка по имени _id отношения или по указанному полю, чтобы гарантировать, что выражения соответствуют выражениям в начале предложения . Например, если модель определяет сортировку по своему полю :DISTINCT ON ORDER BY Blog ordering name

Entry.objects.order_by('blog').distinct('blog')

… Не будет работать, потому что запрос будет отсортирован blog__name и, следовательно, не будет соответствовать выражению . Вам придется явно отсортировать по полю отношения ( в данном случае) или по указанному полю ( ), чтобы убедиться, что два выражения совпадают.DISTINCT ON _id blog_id blog__pk

values()

values( * поля , ** выражения )

Возвращает тот, QuerySet который при повторном использовании возвращает словари вместо экземпляров модели.

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

В этом примере словари сравниваются values() с обычными объектами модели:

# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
<QuerySet [<Blog: Beatles Blog>]>

# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>

Метод values() принимает необязательные позиционные параметры ,, *fields которые определяют имена полей, которыми будет SELECT ограничена инструкция . Если вы заполните эти параметры, каждый словарь в результате будет содержать только ключи / значения указанных полей. Если ни один из этих параметров отсутствует, каждый словарь результата будет содержать ключ и значение для всех полей соответствующей таблицы базы данных.

Пример:

>>> Blog.objects.values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
>>> Blog.objects.values('id', 'name')
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>

Метод values() также принимает необязательные именованные параметры **expressions , которые передаются annotate() :

>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower('name'))
<QuerySet [{'lower_name': 'beatles blog'}]>

Вы можете использовать встроенные или настраиваемые запросы в сортировках. например

>>> from django.db.models import CharField
>>> from django.db.models.functions import Lower
>>> CharField.register_lookup(Lower)
>>> Blog.objects.values('name__lower')
<QuerySet [{'name__lower': 'beatles blog'}]>

Агрегация внутри предложения values() применяется перед другими параметрами в том же предложении. Если вам нужно сгруппировать по другому значению, добавьте его в values() предыдущее предложение . Например :

>>> from django.db.models import Count
>>> Blog.objects.values('entry__authors', entries=Count('entry'))
<QuerySet [{'entry__authors': 1, 'entries': 20}, {'entry__authors': 1, 'entries': 13}]>
>>> Blog.objects.values('entry__authors').annotate(entries=Count('entry'))
<QuerySet [{'entry__authors': 1, 'entries': 33}]>

Стоит упомянуть некоторые тонкости:

  • Если вызываемое поле foo является полем ForeignKey , вызов по values() умолчанию возвращает именованный ключ словаря foo_id , потому что это внутреннее имя атрибута модели, хранящего фактическое значение (атрибут, foo относящийся к связанной модели). Когда вы вызываете values() и предоставляете имена полей, вы можете указать foo или, foo_id и вы получите тот же результат (ключ словаря совпадает с именем указанного вами поля).

    Например :

    >>> Entry.objects.values()
    <QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]>
    
    >>> Entry.objects.values('blog')
    <QuerySet [{'blog': 1}, ...]>
    
    >>> Entry.objects.values('blog_id')
    <QuerySet [{'blog_id': 1}, ...]>
    
  • При использовании values() и использовании в комбинации distinct() помните, что сортировка может повлиять на результаты. См. Примечание distinct() для более подробной информации.

  • Если вы используете пункт values() после вызова extra() , любое поле упоминается в качестве параметра select из extra() должно быть явно включены в вызове values() . При любом вызове extra() после вызова values() дополнительные выбранные поля игнорируются.

  • Вызовы to only() и defer() after values() не имеют смысла, и если вы это сделаете, вы получите исключение NotImplementedError .

  • Комбинирование преобразований и агрегатов требует использования двух вызовов annotate() : либо явно, либо в качестве именованных параметров для meth: values. Как и выше, если преобразование было зарегистрировано для правильного типа поля, первый вызов annotate() можно опустить, что означает, что следующие два примера эквивалентны

    >>> from django.db.models import CharField, Count
    >>> from django.db.models.functions import Lower
    >>> CharField.register_lookup(Lower)
    >>> Blog.objects.values('entry__authors__name__lower').annotate(entries=Count('entry'))
    <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
    >>> Blog.objects.values(
    ...     entry__authors__name__lower=Lower('entry__authors__name')
    ... ).annotate(entries=Count('entry'))
    <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
    >>> Blog.objects.annotate(
    ...     entry__authors__name__lower=Lower('entry__authors__name')
    ... ).values('entry__authors__name__lower').annotate(entries=Count('entry'))
    <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
    

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

Наконец, обратите внимание, что вы можете звонить filter() и order_by() т. Д. после вызова values() , что означает, что эти два вызова идентичны:

Blog.objects.values().order_by('id')
Blog.objects.order_by('id').values()

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

Вы также можете ссылаться на модели, связанные обратными отношениями через атрибуты OneToOneField , ForeignKey и ManyToManyField :

>>> Blog.objects.values('name', 'entry__headline')
<QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
     {'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>

Предупреждение

Поскольку атрибуты ManyToManyField и обратные отношения могут иметь несколько связанных строк, их включение может иметь множительный эффект на размер набора результатов. И чем больше таких полей в запросе values() , тем заметнее эффект, потому что составляются и возвращаются все возможные комбинации.

values_list()

values_list( * fields , flat = False , named = False )

Подобно тому values() , за исключением того, что вместо возврата словарей кортежи возвращаются при повторении результатов. Каждый кортеж содержит значения полей или выражений в соответствующей позиции их появления в поле call to values_list() - first в качестве первого элемента и т. Д. Например :

>>> Entry.objects.values_list('id', 'headline')
<QuerySet [(1, 'First entry'), ...]>
>>> from django.db.models.functions import Lower
>>> Entry.objects.values_list('id', Lower('headline'))
<QuerySet [(1, 'first entry'), ...]>

Если вы указываете только одно поле, вы также можете указать параметр flat . Если он установлен True , это означает, что возвращаемые результаты являются отдельными значениями, а не отдельными кортежами. Этот пример должен прояснить разницу:

>>> Entry.objects.values_list('id').order_by('id')
<QuerySet[(1,), (2,), (3,), ...]>

>>> Entry.objects.values_list('id', flat=True).order_by('id')
<QuerySet [1, 2, 3, ...]>

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

Вы можете переключиться, named=True чтобы получить результаты в виде namedtuple() :

>>> Entry.objects.values_list('id', 'headline', named=True)
<QuerySet [Row(id=1, headline='First entry'), ...]>

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

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

Часто возникает необходимость получить конкретное значение поля из определенного экземпляра модели. Для этого используйте с values_list() последующим вызовом get() :

>>> Entry.objects.values_list('headline', flat=True).get(pk=1)
'First entry'

values() и то и другое values_list() следует рассматривать как оптимизацию для конкретного случая использования: получение подмножества данных без накладных расходов на создание экземпляров модели. Эта метафора больше не работает, когда мы имеем дело с отношениями «многие ко многим» или с многозначными отношениями каким-либо иным образом. (как отношение «один ко многим» обратного внешнего ключа), потому что предположение «одна строка, один объект» больше не выполняется.

Например, обратите внимание на поведение, когда запрос проходит через поле ManyToManyField :

>>> Author.objects.values_list('name', 'entry__headline')
<QuerySet [('Noam Chomsky', 'Impressions of Gaza'),
 ('George Orwell', 'Why Socialists Do Not Believe in Fun'),
 ('George Orwell', 'In Defence of English Cooking'),
 ('Don Quixote', None)]>

Авторы с более чем один Entry более одного раза и авторы , не Entry имеющие None этого поля в качестве значения.

Точно так же при запросе по обратному внешнему ключу None отображается для записей без автора:

>>> Entry.objects.values_list('authors')
<QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]>

dates()

dates( поле , вид , порядок = 'ASC' )

Возвращает тот QuerySet , оценка которого дает список объектов, datetime.date представляющих все доступные даты определенного типа в содержимом QuerySet .

field должно быть именем поля DateField в модели. kind должно быть "year" , "month" , "week" или "day" . Каждый объект datetime.date в списке результатов «усечен» в соответствии с данными type .

  • "year" возвращает список всех различных значений года для поля.
  • "month" возвращает список всех различных значений года / месяца для поля.
  • "week" возвращает список всех различных значений года / недели для поля. Все даты - понедельник.
  • "day" возвращает список всех отдельных значений года / месяца / дня для поля.

order , который по умолчанию 'ASC' должен содержать 'ASC' (в хронологическом порядке) или 'DESC' (в обратном хронологическом порядке). Это указывает, как отсортировать результаты.

Примеры:

>>> Entry.objects.dates('pub_date', 'year')
[datetime.date(2005, 1, 1)]
>>> Entry.objects.dates('pub_date', 'month')
[datetime.date(2005, 2, 1), datetime.date(2005, 3, 1)]
>>> Entry.objects.dates('pub_date', 'week')
[datetime.date(2005, 2, 14), datetime.date(2005, 3, 14)]
>>> Entry.objects.dates('pub_date', 'day')
[datetime.date(2005, 2, 20), datetime.date(2005, 3, 20)]
>>> Entry.objects.dates('pub_date', 'day', order='DESC')
[datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)]
>>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
[datetime.date(2005, 3, 20)]

datetimes()

datetimes( field_name , kind , order = 'ASC' , tzinfo = None , is_dst = None )

Возвращает тот QuerySet , оценка которого дает список объектов, datetime.datetime представляющих все доступные даты определенного типа в содержимом QuerySet .

field_name должно соответствовать имени поля DateTimeField в вашей модели.

kind должно быть "year" , "month" , "week" , "day" , "hour" , "minute" или "second" . Каждый объект datetime.datetime в списке результатов «усечен» в соответствии с данными type .

order , который по умолчанию 'ASC' должен содержать 'ASC' (в хронологическом порядке) или 'DESC' (в обратном хронологическом порядке). Это указывает, как отсортировать результаты.

tzinfo определяет часовой пояс, в который дата и время преобразуются до их усечения. Действительно, дата / время могут быть представлены по-разному в зависимости от активного часового пояса. Этот параметр должен быть объектом datetime.tzinfo . Если установлено None , Django использует текущий часовой пояс . Не имеет значения, когда USE_TZ стоит False .

is_dst указывает, pytz следует ли интерпретировать несуществующие и неоднозначные даты при переходе на летнее время. По умолчанию (когда is_dst=None ) pytz вызывает исключение для таких дат.

Новое в Django 3.1:

Параметр is_dst добавлен.

Заметка

Эта функция выполняет преобразование часового пояса непосредственно в базе данных. В результате база данных должна иметь возможность интерпретировать значение tzinfo.tzname(None) . Это означает следующие требования:

none()

none()

Вызов to none() создает набор запросов, который никогда не возвращает никаких объектов и не генерирует запрос при доступе к его результатам. Набор запросов qs.none() является экземпляром EmptyQuerySet .

Примеры:

>>> Entry.objects.none()
<QuerySet []>
>>> from django.db.models.query import EmptyQuerySet
>>> isinstance(Entry.objects.none(), EmptyQuerySet)
True

all()

all()

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

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

union()

union( * other_qs , all = False )

Использует оператор SQL UNION для объединения двух QuerySet или более результатов. Например :

>>> qs1.union(qs2, qs3)

По UNION умолчанию оператор выбирает только отдельные значения. Чтобы разрешить повторяющиеся значения, используйте параметр all=True .

union() , intersection() и difference() возвращать экземпляры модели типа первого набора запросов, даже если параметры являются наборами запросов из других моделей. Можно передавать разные шаблоны, если список SELECT одинаковый для всех наборов запросов (по крайней мере, типы, имена не являются проблемой, если типы совпадают в одном порядке). В таких ситуациях следует использовать имена столбцов из первого набора запросов в методах, QuerySet применяемых к полученному результату. например

>>> qs1 = Author.objects.values_list('name')
>>> qs2 = Entry.objects.values_list('headline')
>>> qs1.union(qs2).order_by('name')

Кроме того, только операции LIMIT , OFFSET , COUNT(*) , и указания столбцов (то есть, сегментация, счета , сортировки и / ) допускается по предварительному запросу результирующей. С другой стороны, базы данных устанавливают ограничения на операции, разрешенные в комбинированных запросах. Например, большинство баз данных не допускают операторов или комбинированных запросов.ORDER BY count() order_by() values() values_list() LIMIT OFFSET

intersection()

intersection( * other_qs )

Использует оператор SQL INTERSECT для возврата элементов, общих для двух или более QuerySet . Например :

>>> qs1.intersection(qs2, qs3)

См. Информацию union() о некоторых ограничениях.

difference()

difference( * other_qs )

Используйте оператор SQL, EXCEPT чтобы сохранить только элементы, присутствующие в одном, QuerySet но не в других QuerySet . Например :

>>> qs1.difference(qs2, qs3)

См. Информацию union() о некоторых ограничениях.

extra()

extra( select = None , где = None , params = None , tables = None , order_by = None , select_params = None )

Иногда синтаксис запроса Django не может легко выразить WHERE сложное предложение . Для этих крайних случаев Django предоставляет модификатор QuerySet extra() , точку входа для вставки определенных предложений в код SQL, созданный с помощью QuerySet .

Используйте этот метод только в крайнем случае

Это старый API, от которого мы планируем отказаться в какой-то момент. Используйте его, только если вы не можете выразить свой запрос с помощью других методов набора запросов. Если вы вынуждены использовать его, создайте заявку, указав ключевое слово QuerySet.extra и представив свой вариант использования (не забудьте сначала проверить наличие существующих заявок), чтобы мы могли ее улучшить. API QuerySet окончательно удалить extra() . Мы больше не улучшаем и не исправляем ошибки для последнего метода.

Например, это использование extra() :

>>> qs.extra(
...     select={'val': "select col from sometable where othercol = %s"},
...     select_params=(someparam,),
... )

эквивалентно :

>>> qs.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))

Главное преимущество использования в RawSQL том, что его можно настроить output_field при необходимости. Основным недостатком является то, что если вы ссылаетесь на псевдоним таблицы запроса, установленного в необработанном коде SQL, то существует вероятность, что Django изменит этот псевдоним (например, когда набор запросов используется как подзапрос в другом запрос).

Предупреждение

При использовании нужно быть очень осторожным extra() . Во время каждого использования вы должны избегать любого параметра, которым могут управлять пользователи, использующие его params , чтобы защитить себя от атак SQL-инъекций.

Вам также следует избегать заключения заполнителей в кавычки в строке SQL. Этот пример уязвим для SQL-инъекции из-за кавычек %s :

SELECT col FROM sometable WHERE othercol = '%s'  # unsafe!

Вы можете узнать больше о том, как работает защита Django от SQL-инъекций .

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

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

  • select

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

    Пример:

    Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
    

    При этом каждый объект Entry имеет дополнительный атрибут is_recent - логическое значение, указывающее, больше ли pub_date поле объекта, чем 1 января 2006 г.

    Django вставляет данный фрагмент SQL прямо в оператор SELECT . Следовательно, код SQL, полученный в приведенном выше примере, будет выглядеть следующим образом:

    SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
    FROM blog_entry;
    

    Следующий пример более показателен; он выполняет подзапрос, чтобы дать каждому объекту Blog результата атрибут entry_count , целое число, подсчитывающее Entry связанные объекты :

    Blog.objects.extra(
        select={
            'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
        },
    )
    

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

    Код SQL, полученный из приведенного выше примера, даст:

    SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
    FROM blog_blog;
    

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

    В некоторых исключительных случаях может потребоваться передать параметры фрагментам SQL в формате extra(select=...) . Для этого используйте параметр select_params .

    Это будет работать, например:

    Blog.objects.extra(
        select={'a': '%s', 'b': '%s'},
        select_params=('one', 'two'),
    )
    

    Если вам нужно использовать %s литерал внутри строки выбора, используйте последовательность %%s .

  • where / tables

    Можно определить WHERE явные предложения SQL - возможно, для выполнения неявных соединений - используя where . Таблицы могут быть добавлены в предложение SQL вручную с FROM помощью параметра tables .

    where и tables оба принимают список строк. Все параметры where объединяются с остальными критериями поиска оператором «И».

    Пример:

    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
    

    ... можно (примерно) перевести в код SQL, например:

    SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')
    

    Будьте осторожны при использовании параметра, tables если он содержит таблицы, уже использованные в запросе. Когда вы добавляете дополнительные таблицы с помощью параметра tables , Django предполагает, что вы хотите добавить эту таблицу еще раз, если она уже существует. Это проблема, потому что тогда имени таблицы будет присвоен псевдоним. Если таблица появляется в операторе SQL более одного раза, ее имя заменяется псевдонимом, начиная со второго вхождения, чтобы база данных могла различить их. Если затем в where дополнительном параметре вы обратитесь к таблице, которую вы явно добавили, вы получите ошибки.

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

  • order_by

    Если вам необходимо отсортировать результаты запроса с новыми полями или таблицами , которые вы включили в extra() , используйте параметр order_by для extra() и завершить его со списком каналов. Эти поля должны либо соответствовать шаблону (как с order_by() обычными наборами запросов метода ) в форме nom_table.nom_colonne или псевдонимом столбца , определенном в параметре select из extra() .

    Например :

    q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
    q = q.extra(order_by = ['-is_recent'])
    

    Этот код помещает все элементы, для которых is_recent допустимы первые, в результаты True (при сортировке по убыванию, True появляется раньше False ).

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

  • params

    Параметр, where описанный выше, может использовать строки подстановки базы данных, как в стандартном Python ,, '%s' чтобы указать параметры ядра базы данных, которые должны быть автоматически заключены в кавычки. Параметр params представляет собой список дополнительных параметров для использования при замене.

    Пример:

    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    

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

    Ложь:

    Entry.objects.extra(where=["headline='Lennon'"])
    

    Справедливая :

    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    

Предупреждение

Если вы запрашиваете MySQL, обратите внимание, что молчаливое приведение типов в MySQL может привести к неожиданным результатам при смешивании типов. Если запрос предназначен для столбца типа строка, но содержит целочисленное значение, MySQL преобразует тип всех значений в таблице в целое число перед выполнением сравнения. Например, если таблица содержит значения 'abc' , 'def' а запрос содержит , будут выбраны обе строки. Чтобы предотвратить это, перед использованием значения в запросе выполните преобразования типов.WHERE macolonne=0

defer()

defer( * поля )

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

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

Entry.objects.defer("headline", "body")

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

Мы можем звонить несколько раз defer() . Каждый вызов добавляет новые поля к набору отложенных полей:

# Defers both the body and headline fields.
Entry.objects.defer("body").filter(rating=5).defer("headline")

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

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

Blog.objects.select_related().defer("entry__headline", "entry__body")

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

# Load all fields immediately.
my_queryset.defer(None)

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

Заметка

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

Даже если вы думаете, что попали в особую ситуацию, используйте defer () только в том случае, если вы не можете определить во время загрузки запроса, понадобятся ли вам дополнительные поля или нет . Если вы часто загружаете и используете определенное подмножество данных, лучшим решением будет нормализовать ваши модели и поместить выгруженные данные в отдельную модель (следовательно, в другую таблицу базы данных). Если столбцы должны оставаться в одной таблице по определенной причине, создайте шаблон с (см. Документацию по атрибутам ), содержащий только поля, которые вам обычно нужны для загрузки, и используйте этот шаблон там, где вы будете использовать.Meta.managed = False managed defer() , Это делает ваш код более понятным, немного более быстрым и потребляет немного меньше памяти в процессе Python.

Например, обе эти модели используют одну и ту же таблицу базы данных в фоновом режиме:

class CommonlyUsedModel(models.Model):
    f1 = models.CharField(max_length=10)

    class Meta:
        managed = False
        db_table = 'app_largetable'

class ManagedModel(models.Model):
    f1 = models.CharField(max_length=10)
    f2 = models.CharField(max_length=10)

    class Meta:
        db_table = 'app_largetable'

# Two equivalent QuerySets:
CommonlyUsedModel.objects.all()
ManagedModel.objects.all().defer('f2')

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

Заметка

При вызове save() экземпляров с отложенными полями сохраняются только загруженные поля. Подробнее save() см.

only()

only( * поля )

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

Предположим, что модель имеет поля name , age и biography . Следующие два запроса идентичны с точки зрения отложенных полей:

Person.objects.defer("age", "biography")
Person.objects.only("name")

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

# This will defer all fields except the headline.
Entry.objects.only("body", "rating").only("headline")

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

# Final result is that everything except "headline" is deferred.
Entry.objects.only("headline", "body").defer("body")

# Final result loads headline and body immediately (only() replaces any
# existing set of fields).
Entry.objects.defer("body").only("headline", "body")

Все предупреждения в документации defer() также относятся к only() . Используйте его осторожно и только после того, как исчерпаете другие возможные варианты.

Также ошибкой является использование d ” only() при пропуске поля, запрошенного пользователем select_related() .

Заметка

При вызове save() экземпляров с отложенными полями сохраняются только загруженные поля. Подробнее save() см.

using()

using( псевдоним )

Этот метод используется для управления базой данных, которая будет целью оценки QuerySet в случае, если определено несколько баз данных. Единственный параметр, разрешенный этим методом, - это псевдоним базы данных, как определено в DATABASES .

Например :

# queries the database with the 'default' alias.
>>> Entry.objects.all()

# queries the database with the 'backup' alias
>>> Entry.objects.using('backup')

select_for_update()

select_for_update( nowait = False , skip_locked = False , of = () )

Возвращает набор запросов, который блокирует строки до завершения транзакции, генерируя инструкцию SQL для поддерживающих ее баз данных.SELECT ... FOR UPDATE

Например :

from django.db import transaction

entries = Entry.objects.select_for_update().filter(author=request.user)
with transaction.atomic():
    for entry in entries:
        ...

Когда набор запросов оценивается ( в этом случае), все совпадающие строки базы данных блокируются до конца блока транзакции, что означает, что другие транзакции не смогут изменять или блокировать самостоятельно. эти строки.for entry in entries

Обычно, если другая транзакция уже заблокировала одну из выбранных строк, запрос блокируется в ожидании снятия блокировки. Если это не то, что вы хотите, позвоните select_for_update(nowait=True) . Тогда вызов будет неблокирующим. Если блокировка уже установлена ​​другой транзакцией для одного из выбираемых элементов, DatabaseError во время оценки набора запросов генерируется исключение . Также можно игнорировать заблокированные строки, используя вместо этого select_for_update(skip_locked=True) . Параметры nowait и skip_locked являются взаимоисключающими; если они оба включены при вызове select_for_update() , ValueError будет сгенерирована ошибка .

По умолчанию select_for_update() блокирует все строки, выбранные запросом. Например, строки связанных объектов, упомянутых в select_related() , блокируются в дополнение к строкам модели набора запросов. Если это не требуется, укажите связанные объекты, которые вы хотите заблокировать, select_for_update(of=(...)) используя тот же синтаксис имени поля, что и для select_related() . Используйте значение 'self' для ссылки на модель набора запросов.

Заблокировать родительские модели в select_for_update(of=(...))

Если вы хотите заблокировать родительские модели в контексте множественного наследования , вы должны указать поля родительской ссылки (по умолчанию <parent_model_name>_ptr ) в параметре of . например

Restaurant.objects.select_for_update(of=('self', 'place_ptr'))

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

>>> Person.objects.select_related('hometown').select_for_update()
Traceback (most recent call last):
...
django.db.utils.NotSupportedError: FOR UPDATE cannot be applied to the nullable side of an outer join

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

>>> Person.objects.select_related('hometown').select_for_update().exclude(hometown=None)
<QuerySet [<Person: ...)>, ...]>

На данный момент, база данных двигателей postgresql , oracle и mysql поддержки select_for_update() . Тем не менее, MariaDB 10.3+ управляет только параметр nowait и MySQL 8.0.1+ управляет nowait и параметров skip_locked . MySQL и MariaDB не поддерживают этот параметр of .

Если вы проходите nowait=True , skip_locked=True или of к select_for_update() и Database Engine не поддерживает эти параметры, как и с MySQL, исключение NotSupportedError выбрасывается. Это сделано для предотвращения неожиданной блокировки кода.

Оценка набора запросов select_for_update() в режиме автоматической фиксации с базами данных, которые его поддерживают, является ошибкой, потому что в этом случае строки не заблокированы. Если бы это было разрешено, это был бы вектор повреждения данных, который легко мог бы быть вызван вызывающим кодом, предназначенным для выполнения в транзакции вне транзакции.SELECT ... FOR UPDATE TransactionManagementError

Использование select_for_update() с движками, которые не поддерживают (например, SQLite), не даст никакого эффекта. не будет добавлен в запрос, и при использовании в режиме автоматической фиксации не будет возникать ошибка .SELECT ... FOR UPDATE SELECT ... FOR UPDATE select_for_update()

Предупреждение

Даже если select_for_update() в режиме автофиксации обычно происходит сбой, поскольку TestCase каждый тест автоматически включает транзакцию, вызов с select_for_update() точностью до одного, TestCase даже вне блока atomic() , пройдет (возможно, неожиданно) без генерации исключения TransactionManagementError . Для правильного тестирования select_for_update() вы должны использовать TransactionTestCase .

Некоторые выражения могут не поддерживаться

PostgreSQL не поддерживает select_for_update() выражения с расширением Window .

raw()

raw( raw_query , params = None , translations = None )

Принимает необработанный запрос SQL, выполняет его и возвращает экземпляр django.db.models.query.RawQuerySet . Затем можно выполнить цикл для этого экземпляра так RawQuerySet же, как для QuerySet обычного объекта , чтобы получить доступ к экземплярам объекта.

Дополнительные сведения см. В разделе « Запуск необработанных SQL-запросов» .

Предупреждение

raw() всегда генерирует новый запрос и не принимает во внимание предыдущие фильтрации. Таким образом, его обычно следует вызывать только из совершенно нового Manager экземпляра QuerySet .

Операторы, возвращающие новые QuerySet

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

И ( & )

Объединяет два запроса QuerySet с помощью оператора SQL AND (И).

Следующие запросы эквивалентны

Model.objects.filter(x=1) & Model.objects.filter(y=2)
Model.objects.filter(x=1, y=2)
from django.db.models import Q
Model.objects.filter(Q(x=1) & Q(y=2))

Эквивалент SQL:

SELECT ... WHERE x=1 AND y=2

ИЛИ ( | )

Объедините два запроса QuerySet с помощью оператора SQL OR (ИЛИ).

Следующие запросы эквивалентны

Model.objects.filter(x=1) | Model.objects.filter(y=2)
from django.db.models import Q
Model.objects.filter(Q(x=1) | Q(y=2))

Эквивалент SQL:

SELECT ... WHERE x=1 OR y=2

Методы, которые не возвращаются QuerySet

QuerySet Следующие методы оценивают QuerySet и возвращают что-то другое, кроме единицы QuerySet .

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

get()

get( ** kwargs )

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

Entry.objects.get(id=1)
Entry.objects.get(blog=blog, entry_number=1)

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

Entry.objects.filter(pk=1).get()

Если get() не находит ни одного объекта, генерируется исключение Model.DoesNotExist :

Entry.objects.get(id=-999) # raises Entry.DoesNotExist

Если get() находит более одного объекта, генерируется исключение Model.MultipleObjectsReturned :

Entry.objects.get(name='A Duplicated Name') # raises Entry.MultipleObjectsReturned

Эти два класса исключений являются атрибутами класса модели и специфичны для этих моделей. Если вы хотите перехватывать такие исключения из нескольких вызовов get() для разных моделей, вы можете использовать их общий базовый класс. Например, вы можете использовать django.core.exceptions.ObjectDoesNotExist для перехвата исключений DoesNotExist из разных моделей

from django.core.exceptions import ObjectDoesNotExist

try:
    blog = Blog.objects.get(id=1)
    entry = Entry.objects.get(blog=blog, entry_number=1)
except ObjectDoesNotExist:
    print("Either the blog or entry doesn't exist.")

create()

create( ** kwargs )

Метод утверждения для создания объекта и регистрации его одним методом. Так :

p = Person.objects.create(first_name="Bruce", last_name="Springsteen")

и:

p = Person(first_name="Bruce", last_name="Springsteen")
p.save(force_insert=True)

эквивалентны.

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

get_or_create()

get_or_create(по умолчанию = Нет , ** kwargs )

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

Возвращает кортеж, в котором загружен или создан объект, и является логическим значением, указывающим, был ли создан новый объект.(objet, créé) objet créé

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

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()

Здесь возможно, что несколько параллельных запросов пытаются сохранить один Person с одинаковыми параметрами. Чтобы избежать этого состояния гонки, приведенный выше пример можно переписать get_or_create() следующим образом:

obj, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

Любой именованный параметр передается get_or_create() - за исключением дополнительного параметра называется defaults - будет использоваться в вызове get() . Если объект найден, get_or_create() возвращает кортеж, состоящий из этого объекта плюс False .

Предупреждение

Этот метод является атомарным, предполагая, что база данных обеспечивает уникальность названных параметров (см. unique Или unique_together ). Если поля, используемые в названных параметрах, не имеют ограничения уникальности, одновременные вызовы этого метода могут привести к вставке нескольких строк с одинаковыми значениями.

Вы можете задать более сложные условия для объекта , чтобы найти приковав get_or_create() с filter() и использованием . Например, чтобы восстановить Роберта или Боба Марли, если один из двух существует, и создать последнего, если нетobjets Q

from django.db.models import Q

obj, created = Person.objects.filter(
    Q(first_name='Bob') | Q(first_name='Robert'),
).get_or_create(last_name='Marley', defaults={'first_name': 'Bob'})

Если было найдено несколько объектов, get_or_create() сгенерируйте MultipleObjectsReturned . Если объект не был найден, get_or_create() создайте экземпляр объекта и зарегистрируйте его, вернув кортеж, состоящий из этого нового объекта и True . Новый объект будет создан примерно по этому алгоритму.

params = {k: v for k, v in kwargs.items() if '__' not in k}
params.update({k: v() if callable(v) else v for k, v in defaults.items()})
obj = self.model(**params)
obj.save()

По-французски это означает, что мы начинаем с любого именованного параметра, отличного от 'defaults' и который не содержит двойного подчеркивания (что указывает на неточный поиск). Затем мы добавляем содержимое 'defaults' , перегружая любые существующие параметры, и используем результат как именованные параметры класса модели. Если defaults содержит исполняемые элементы, они оцениваются. Как уже было сказано, это упрощение реального алгоритма, но все важные части присутствуют. Фактическая реализация содержит некоторые дополнительные проверки на ошибки и устраняет некоторые экстремальные условия; если интересно, прочтите код.

Если у вас есть именованное поле defaults и вы хотите использовать его для точного поиска get_or_create() , укажите это 'defaults__exact' , например:

Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})

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

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

Предупреждение

Вы можете использовать get_or_create() через атрибуты ManyToManyField и обратные отношения. В этом случае вы ограничите запросы в контексте этой связи. Некоторые проблемы с целостностью могут возникнуть, если вы не используете его постоянно.

Рассматривая следующие модели:

class Chapter(models.Model):
    title = models.CharField(max_length=255, unique=True)

class Book(models.Model):
    title = models.CharField(max_length=256)
    chapters = models.ManyToManyField(Chapter)

Вы можете использовать get_or_create() через поле chapters из Book , но он рассматривает только объекты в контексте этого Book :

>>> book = Book.objects.create(title="Ulysses")
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, True)
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, False)
>>> Chapter.objects.create(title="Chapter 1")
<Chapter: Chapter 1>
>>> book.chapters.get_or_create(title="Chapter 1")
# Raises IntegrityError

Это происходит потому, что он пытается получить или создать «Главу 1» через книгу «Улисс», но он не может сделать ни того, ни другого: отношение не может получить эту главу, поскольку 'его нет в этой книге, но он также не может его создать, потому что поле title должно быть уникальным.

update_or_create()

update_or_create(по умолчанию = Нет , ** kwargs )

Служебный метод для обновления объекта kwargs заданными параметрами , при необходимости создавая новый объект. Параметр defaults - это словарь пар (поле, значение), используемых для обновления объекта. Значения в defaults могут быть исполняемыми.

Возвращает кортеж, в котором создается созданный или обновленный объект, и является логическим значением, указывающим, был ли создан новый объект.(objet, créé) objet créé

Метод update_or_create пытается получить объект из базы данных на основе kwargs указанных параметров . Если совпадение найдено, оно обновляет поля, переданные в словарь defaults .

Намерение состоит в том, чтобы предоставить ярлык вместо повторения кода. Например :

defaults = {'first_name': 'Bob'}
try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
    for key, value in defaults.items():
        setattr(obj, key, value)
    obj.save()
except Person.DoesNotExist:
    new_values = {'first_name': 'John', 'last_name': 'Lennon'}
    new_values.update(defaults)
    obj = Person(**new_values)
    obj.save()

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

obj, created = Person.objects.update_or_create(
    first_name='John', last_name='Lennon',
    defaults={'first_name': 'Bob'},
)

Подробное описание того, как переданные имена kwargs разрешаются, см get_or_create() . В разделе .

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

Подобно get_or_create() и create() , если вы устанавливаете первичные ключи вручную и объект должен быть создан, но первичный ключ уже существует в базе данных, генерируется исключение IntegrityError .

bulk_create()

bulk_create( objs , batch_size = None , ignore_conflicts = False )

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

>>> Entry.objects.bulk_create([
...     Entry(headline='This is a test'),
...     Entry(headline='This is only a test'),
... ])

Однако у этого метода есть некоторые недостатки:

  • Метод save() каждой модели не вызывается, а сигналы pre_save и post_save не отправляются.

  • Он не работает с дочерними моделями в контексте многотабличного наследования.

  • Если первичным ключом модели является an AutoField , атрибут первичного ключа можно получить только в определенных базах данных (в настоящее время PostgreSQL и MariaDB 10.5+). В других базах он не будет установлен.

  • Это не работает с отношениями "многие ко многим".

  • Это заставляет objs быть список, который полностью оценивает objs , является ли он генератором. Это форсирование позволяет проверять все объекты, так что любой объект с определенным вручную первичным ключом вставляется первым. Если вы хотите вставлять объекты группами без предварительной оценки всего построителя, вы можете использовать этот метод, если у объектов нет вручную определенного первичного ключа.

    from itertools import islice
    
    batch_size = 100
    objs = (Entry(headline='Test %s' % i) for i in range(1000))
    while True:
        batch = list(islice(objs, batch_size))
        if not batch:
            break
        Entry.objects.bulk_create(batch, batch_size)
    

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

Для баз данных, которые его поддерживают (всех, кроме Oracle), установка параметра ignore_conflicts в значение True указывает базе данных игнорировать ошибки вставки строк, которые нарушают ограничения, такие как значения уникальные дубликаты. Включение этого параметра отключает возможность установки первичного ключа для каждого экземпляра модели (если база данных управляет им нормально).

Предупреждение

С MySQL и MariaDB, когда вы указываете параметр ignore_conflicts на True определенные типы , кроме дубликата ключа ошибки преобразуются в предупреждения, даже в строгом режиме. Например: недопустимые значения или ненулевые нарушения поля. См. Документацию MySQL и MariaDB для получения более подробной информации.

Возвращает objs как приведенный к списку, в том же порядке, как указано.

Изменено в Django 3.1:

Добавлена ​​поддержка получения атрибутов первичного ключа в MariaDB 10.5+.

bulk_update()

bulk_update( objs , fields , batch_size = None )

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

>>> objs = [
...    Entry.objects.create(headline='Entry 1'),
...    Entry.objects.create(headline='Entry 2'),
... ]
>>> objs[0].headline = 'This is entry 1'
>>> objs[1].headline = 'This is entry 2'
>>> Entry.objects.bulk_update(objs, ['headline'])

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

  • Невозможно обновить первичный ключ моделей.
  • Метод save() моделей не вызывается, а сигналы pre_save и post_save не отправляются.
  • Если обновление включает в себя большое количество столбцов для большого количества строк, сгенерированный код SQL может стать очень большим. Избегайте этого, задав batch_size соответствующее значение .
  • Обновление полей, определенных в родительских экземплярах в контексте многотабличного наследования, приведет к созданию дополнительного запроса для каждого родителя.
  • Если objs содержит дубликаты, обновляется только первый.

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

count()

count()

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

Пример:

# Returns the total number of entries in the database.
Entry.objects.count()

# Returns the number of entries whose headline contains 'Lennon'
Entry.objects.filter(headline__contains='Lennon').count()

Обращение к count() генерирует оператор в фоновом режиме, поэтому рекомендуется всегда использовать, а не загружать все результаты как объекты Python и вызывать этот список объектов (кроме случаев, когда вам нужно загружать объекты в память, в этом случае будет быстрее).SELECT COUNT(*) count() len() len()

Обратите внимание, что если вы хотите получить количество элементов, равное единице, QuerySet и вы также собираетесь использовать его экземпляры модели (например, в итерации), вероятно, более эффективно использовать, len(queryset) что не приведет к созданию запроса к базе данных. дополнительный как бы count() .

in_bulk()

in_bulk( id_list = Нет , field_name = 'pk' )

Принимает список значений поля ( id_list ) вместе с именем, field_name соответствующим этим значениям, и возвращает словарь, который сопоставляет каждое значение с экземпляром объекта с заданным значением поля. Если id_list не указан, возвращаются все объекты в наборе запроса. field_name должно быть уникальным полем и по умолчанию представлять первичный ключ,

Пример:

>>> Blog.objects.in_bulk([1])
{1: <Blog: Beatles Blog>}
>>> Blog.objects.in_bulk([1, 2])
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
>>> Blog.objects.in_bulk([])
{}
>>> Blog.objects.in_bulk()
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>, 3: <Blog: Django Weblog>}
>>> Blog.objects.in_bulk(['beatles_blog'], field_name='slug')
{'beatles_blog': <Blog: Beatles Blog>}

Если передать пустой список в in_bulk() , то получится пустой словарь.

iterator()

iterator( chunk_size = 2000 )

Оценивает его QuerySet (путем выполнения запроса) и возвращает итератор (см.PEP 234 ) по результатам. QuerySet ОбычноAкэширует свои результаты во внутреннем кэше, чтобы дальнейшие вычисления не вызывали дополнительных запросов. Лучшеiterator() читать результаты напрямую, ничего не кэшируяQuerySet (внутренне итератор по умолчанию вызываетiterator() и кэширует возвращаемое значение). ДляQuerySet возврата большого количества объектов, к которым вам нужно получить доступ только один раз, это может привести к повышению производительности и гораздо меньшему использованию памяти.

Обратите внимание , что использование iterator() на одном , который QuerySet уже оценили силы новой оценку, повторив запрос.

Кроме того, использование итератора () игнорирует любые предыдущие вызовы prefetch_related() , потому что не имеет смысла объединять эти две оптимизации.

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

С курсорами на стороне сервера

Oracle и PostgreSQL используют серверные курсоры для потоковой передачи результатов в базу данных без загрузки всего набора результатов в память.

Драйвер базы данных Oracle всегда использует серверные курсоры.

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

С PostgreSQL, серверные курсоры используются только тогда , когда установка DISABLE_SERVER_SIDE_CURSORS будет установлена False . Прочтите Массовые транзакции и Курсоры на стороне сервера, если вы используете концентратор соединений, настроенный в режиме концентрации транзакций. Когда курсоры на стороне сервера отключены, поведение такое же, как и для баз данных, которые не поддерживают эти курсоры.

Без серверных курсоров

MySQL не поддерживает распределение результатов, а это означает, что драйвер Python для этой базы данных загружает весь набор результатов в память. Затем этот набор результатов преобразуется в объекты строк Python адаптером базы данных с использованием метода, fetchmany() определенного вPEP 249 .

SQLite может получать результаты в пакетном режиме fetchmany() , но поскольку SQLite не обеспечивает изоляцию между запросами внутри соединения, будьте осторожны при записи в таблицу, в которой в данный момент выполняется поиск. См. Раздел Изоляция при использовании QuerySet.iterator () для получения дополнительной информации.

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

Значение по умолчанию chunk_size 2000 получено из расчета в списке рассылки psycopg :

Представляя строки из 10-20 столбцов со смесью текстовых и числовых данных, 2000 восстановит менее 100 КБ данных, что кажется хорошим компромиссом между количеством переданных строк и данными, которые должны быть отброшены в случае 'преждевременный выход из цикла.

latest()

latest( * поля )

Возвращает последний объект в таблице на основе указанного поля (полей).

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

Entry.objects.latest('pub_date')

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

Entry.objects.latest('pub_date', '-expire_date')

Знак минус '-expire_date' указывает на то, что мы хотим отсортировать expire_date в порядке убывания . По мере latest() получения последнего результата выбирается тот, Entry у которого самая expire_date старая дата .

Если определяется мета- класс модели get_latest_by , можно опустить любой параметр в earliest() и latest() . Поля, определенные в, get_latest_by будут использоваться по умолчанию.

Как get() , earliest() и latest() генерировать , DoesNotExist если объект не соответствует заданным параметрам.

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

earliest() и latest() может возвращать экземпляры с нулевыми датами.

Поскольку сортировка делегирована базе данных, результаты полей, допускающих значения NULL, могут сортироваться по-разному в зависимости от базы данных. Например, PostgreSQL и MySQL сортируют нулевые значения, как если бы они были больше ненулевых значений, в то время как SQLite делает наоборот.

Может быть желательно исключить нулевые значения:

Entry.objects.filter(pub_date__isnull=False).latest('pub_date')

earliest()

earliest( * поля )

Работает вроде latest() , но наоборот.

first()

first()

Возвращает первый объект в наборе запроса или, None если запрос пуст. Если объект QuerySet не отсортирован, запрос автоматически сортируется по первичному ключу. Это может повлиять на совокупные результаты, как описано в разделе «Взаимодействие с сортировкой по умолчанию или order_by ()» .

Пример:

p = Article.objects.order_by('title', 'pub_date').first()

Обратите внимание, что first() это метод аккредитации; следующий фрагмент кода эквивалентен приведенному выше примеру:

try:
    p = Article.objects.order_by('title', 'pub_date')[0]
except IndexError:
    p = None

last()

last()

Работает аналогично first() , но возвращает последний объект в наборе запроса.

aggregate()

aggregate( * аргументы , ** kwargs )

Возвращает словарь агрегированных значений (средних, сумм и т. Д.), Рассчитанных в QuerySet . Каждый параметр d aggregate() определяет значение, которое будет включено в возвращаемый словарь.

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

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

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

>>> from django.db.models import Count
>>> q = Blog.objects.aggregate(Count('entry'))
{'entry__count': 16}

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

>>> q = Blog.objects.aggregate(number_of_entries=Count('entry'))
{'number_of_entries': 16}

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

exists()

exists()

Возвращает, True если QuerySet содержит хотя бы один результат, в противном случае False . Этот метод пытается сделать запрос максимально простым и быстрым , насколько это возможно, но запрос выполняется это почти идентичен с QuerySet нормальным.

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

Самый эффективный способ определить, присутствует ли шаблон с уникальным полем (например, его первичный ключ) в a QuerySet :

entry = Entry.objects.get(pk=123)
if some_queryset.filter(pk=entry.pk).exists():
    print("Entry contained in queryset")

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

if entry in some_queryset:
   print("Entry contained in QuerySet")

И чтобы узнать, содержит ли набор запросов хотя бы один элемент:

if some_queryset.exists():
    print("There is at least one object in some_queryset")

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

if some_queryset:
    print("There is at least one object in some_queryset")

… Но не намного (чем больше потенциально большой набор запросов, тем выше выплата).

Кроме того, если он some_queryset еще не был оценен, но вы знаете, что в какой-то момент это произойдет, вызов to some_queryset.exists() выполняет некоторую дополнительную работу (один запрос на проверку существования плюс еще один позже. при загрузке результатов) против bool(some_queryset) , который извлекает результаты, а затем проверяет, есть ли хотя бы один.

update()

update( ** kwargs )

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

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

>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)

(Предполагается , что ваша модель Entry содержит pub_date и поле comments_on .)

Вы можете обновить несколько полей; Нет предела. В следующем примере мы обновляем comments_on и поля headline :

>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False, headline='This is old')

Метод update() применяется немедленно, и единственное ограничение на QuerySet обновление состоит в том, что оно может обновлять только столбцы в основной таблице модели, но не в связанных моделях. Например, это невозможно:

>>> Entry.objects.update(blog__name='foo') # Won't work!

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

>>> Entry.objects.filter(blog__id=1).update(comments_on=True)

Вы не можете обратиться update() к той QuerySet , которая подверглась сегментации или которая больше не может быть проверена по какой-либо другой причине.

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

>>> Entry.objects.filter(id=64).update(comments_on=True)
1

>>> Entry.objects.filter(slug='nonexistent-slug').update(comments_on=True)
0

>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
132

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

e = Entry.objects.get(id=10)
e.comments_on = False
e.save()

... сделай это:

Entry.objects.filter(id=10).update(comments_on=False)

Использование d » update() также позволяет избежать ситуации параллелизма, когда содержимое в базе данных может быть изменено в короткий интервал между загрузкой объекта и вызовом save() .

И, наконец, понимает , что update() выполняет обновление на уровне SQL и , следовательно , не вызывает save() модель способа , ни излучать pre_save и сигналы post_save (которые являются следствием вызова Model.save() ). Если вы хотите обновить несколько объектов в модели, у которых есть save() собственный метод , пропустите их через цикл, вызвав save() , например:

for e in Entry.objects.filter(pub_date__year=2010):
    e.comments_on = False
    e.save()

delete()

delete()

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

Удаление вступает в delete() силу немедленно. Вы не можете обратиться delete() к той QuerySet , которая подверглась сегментации или которая больше не может быть проверена по какой-либо другой причине.

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

>>> b = Blog.objects.get(pk=1)

# Delete all the entries belonging to this Blog.
>>> Entry.objects.filter(blog=b).delete()
(4, {'weblog.Entry': 2, 'weblog.Entry_authors': 2})

По умолчанию поля ForeignKey Django имитируют поведение ограничения SQL . Другими словами, любой объект, имеющий внешние ключи к удаляемым объектам, также будет удален. Например :ON DELETE CASCADE

>>> blogs = Blog.objects.all()

# This will delete all Blogs and all of their Entry objects.
>>> blogs.delete()
(5, {'weblog.Blog': 1, 'weblog.Entry': 2, 'weblog.Entry_authors': 2})

Это каскадное поведение можно настроить с помощью настройки on_delete из ForeignKey .

Метод delete() удаляет массив и не вызывает метод delete() шаблонов. С другой стороны, он излучает сигналы pre_delete и post_delete для всех удаленных объектов (включая каскадные удаления).

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

Внешние ключи параметры которых on_delete является DO_NOTHING (не делать ничего) не предотвратить ускоренное удаление.

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

as_manager()

classmethodas_manager ()

Метод класса, который возвращает экземпляр Manager с копией методов QuerySet . Дополнительные сведения см. В разделе « Создание объектов диспетчера с помощью методов QuerySet» .

explain()

explain( формат = Нет , ** параметры )

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

Например, с PostgreSQL

>>> print(Blog.objects.filter(title='My Blog').explain())
Seq Scan on blog  (cost=0.00..35.50 rows=10 width=12)
  Filter: (title = 'My Blog'::bpchar)

Результат значительно различается между базами данных.

explain() поддерживается всеми встроенными механизмами баз данных, кроме Oracle, поскольку реализация для Oracle не является простой.

format Параметр изменяет формат вывода из умолчанию в базах данных, которая, как правило , на основе текста. PostgreSQL поддерживает 'TEXT' , 'JSON' , 'YAML' , и 'XML' форматы. MariaDB и MySQL поддерживают 'TEXT' (также называемые 'TRADITIONAL' ) и 'JSON' форматы. MySQL 8.0.16+ также поддерживает улучшенный 'TREE' формат, который похож на 'TEXT' вывод PostgreSQL и используется по умолчанию, если поддерживается.

Некоторые базы данных принимают параметры, которые могут возвращать дополнительную информацию о запросе. Передайте эти параметры как именованные параметры. Например, с PostgreSQL

>>> print(Blog.objects.filter(title='My Blog').explain(verbose=True))
Seq Scan on public.blog  (cost=0.00..35.50 rows=10 width=12) (actual time=0.004..0.004 rows=10 loops=1)
  Output: id, title
  Filter: (blog.title = 'My Blog'::bpchar)
Planning time: 0.064 ms
Execution time: 0.058 ms

В некоторых базах данных флаги могут вызывать выполнение запроса, что может иметь неблагоприятные последствия для вашей базы данных. Например, ANALYZE флаг, поддерживаемый MariaDB, MySQL 8.0.18+ и PostgreSQL, может привести к изменениям данных при наличии триггеров или при вызове функции даже для SELECT запроса.

Изменено в Django 3.1:

'TREE' Добавлена поддержка формата в MySQL 8.0.16+ и analyze опция в MariaDB и MySQL 8.0.18+.

Полевые поиски

Поиск по полям - это то, что составляет основу предложений SQL WHERE . Синтаксис выражается параметров , указанных в методах filter() , exclude() и get() в QuerySet .

Для введения в этот раздел см. Документацию по моделям и запросам к базе данных .

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

Для удобства, когда конкретный поиск не указан (как в Entry.objects.get(id=14) ), Django предполагает, что это желаемый поиск exact .

exact

Полное совпадение. Если значение, предоставленное для сравнения, является допустимым None , оно будет интерпретировано как NULL SQL ( isnull подробнее см.).

Примеры:

Entry.objects.get(id__exact=14)
Entry.objects.get(id__exact=None)

Эквивалентность в SQL:

SELECT ... WHERE id = 14;
SELECT ... WHERE id IS NULL;

MySQL сравнения

В MySQL параметр "сопоставление" таблицы базы данных определяет, exact учитываются ли при сравнении регистр. Это настройка базы данных, а не Django. Можно настроить таблицы MySQL для использования сравнений с учетом регистра, но это предполагает некоторые компромиссы. Дополнительные сведения об этом см. В разделе сопоставления документации по базе данных .

iexact

Точное совпадение без учета регистра. Если значение, предоставленное для сравнения, является допустимым None , оно будет интерпретировано как NULL SQL ( isnull подробнее см.).

Пример:

Blog.objects.get(name__iexact='beatles blog')
Blog.objects.get(name__iexact=None)

Эквивалентность в SQL:

SELECT ... WHERE name ILIKE 'beatles blog';
SELECT ... WHERE name IS NULL;

Обратите внимание, что , и т. Д. все соответствуют первому поиску.'Beatles Blog' 'beatles blog' 'BeAtLes BLoG'

Пользователи SQLite

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

contains

Проверка включения с учетом регистра.

Пример:

Entry.objects.get(headline__contains='Lennon')

Эквивалент SQL:

SELECT ... WHERE headline LIKE '%Lennon%';

Обратите внимание, что title ( headline ) будет соответствовать этому поиску, но не .'Lennon honored today' 'lennon honored today'

Пользователи SQLite

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

icontains

Тест включения без учета регистра.

Пример:

Entry.objects.get(headline__icontains='Lennon')

Эквивалент SQL:

SELECT ... WHERE headline ILIKE '%Lennon%';

Пользователи SQLite

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

in

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

Примеры:

Entry.objects.filter(id__in=[1, 3, 4])
Entry.objects.filter(headline__in='abc')

Эквивалентность в SQL:

SELECT ... WHERE id IN (1, 3, 4);
SELECT ... WHERE headline IN ('a', 'b', 'c');

Вы также можете использовать набор запросов для динамической оценки списка значений вместо предоставления списка литеральных значений:

inner_qs = Blog.objects.filter(name__contains='Cheddar')
entries = Entry.objects.filter(blog__in=inner_qs)

Этот набор запросов будет оцениваться как оператор подвыбора:

SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')

Если вы предоставляете QuerySet результат вызова values() или values_list() значение запроса __in , вы должны убедиться, что вы извлекаете из результата одно поле. Например, это будет работать (фильтрация по названиям блогов):

inner_qs = Blog.objects.filter(name__contains='Ch').values('name')
entries = Entry.objects.filter(blog__name__in=inner_qs)

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

# Bad code! Will raise a TypeError.
inner_qs = Blog.objects.filter(name__contains='Ch').values('name', 'id')
entries = Entry.objects.filter(blog__name__in=inner_qs)

Соображения производительности

Будьте осторожны с вложенными запросами; это вопрос хорошего понимания ставок на уровне производительности сервера базы данных (если есть сомнения, проведите тесты производительности). Некоторые механизмы баз данных, в первую очередь MySQL, не очень хорошо оптимизируют подзапросы. В этих ситуациях более эффективно извлечь значения в виде списка и затем передать их второму запросу. Понятно, что нужно выполнить два запроса вместо одного:

values = Blog.objects.filter(
        name__contains='Cheddar').values_list('pk', flat=True)
entries = Entry.objects.filter(blog__in=list(values))

Обратите внимание на призыв list() в QuerySet блоге принудительно выполнить первый запрос. Без него подзапрос будет выполнен, поскольку объекты QuerySet отложены .

gt

Больше чем.

Пример:

Entry.objects.filter(id__gt=4)

Эквивалент SQL:

SELECT ... WHERE id > 4;

gte

Больше или равно.

lt

Меньше чем.

lte

Меньше или равно.

startswith

Начинается с (с учетом регистра).

Пример:

Entry.objects.filter(headline__startswith='Lennon')

Эквивалент SQL:

SELECT ... WHERE headline LIKE 'Lennon%';

SQLite не поддерживает операторы, LIKE чувствительные к регистру; startswith ведет себя как istartswith SQLite.

istartswith

Начинается с (без учета регистра).

Пример:

Entry.objects.filter(headline__istartswith='Lennon')

Эквивалент SQL:

SELECT ... WHERE headline ILIKE 'Lennon%';

Пользователи SQLite

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

endswith

Заканчивается на (с учетом регистра).

Пример:

Entry.objects.filter(headline__endswith='Lennon')

Эквивалент SQL:

SELECT ... WHERE headline LIKE '%Lennon';

Пользователи SQLite

SQLite не поддерживает операторы, LIKE чувствительные к регистру; endswith ведет себя как iendswith SQLite. См. Примечания к базе данных для получения дополнительной информации.

iendswith

Заканчивается на (без учета регистра).

Пример:

Entry.objects.filter(headline__iendswith='Lennon')

Эквивалент SQL:

SELECT ... WHERE headline ILIKE '%Lennon'

Пользователи SQLite

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

range

Интервальный тест (включительно).

Пример:

import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))

Эквивалент SQL:

SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';

Вы можете использовать его range где угодно или можете использовать BETWEEN SQL - для дат, чисел и даже символов.

Предупреждение

Фильтрация по полю DateTimeField с датами не будет включать объекты за последний день, потому что ограничения интерпретируются как «полночь в указанную дату». Если бы это pub_date было поле DateTimeField , приведенное выше выражение соответствовало бы следующему коду SQL:

SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';

Как правило, нельзя смешивать дату и объекты даты / времени.

date

Для полей даты и времени принудительно устанавливает значение даты. За этим выражением могут следовать другие выражения поля. Принимает значение даты.

Пример:

Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

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

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

year

Для полей даты и даты / времени - точное совпадение года. За этим выражением могут следовать другие выражения поля. Примите год как целое число.

Пример:

Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)

Эквивалент SQL:

SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
SELECT ... WHERE pub_date >= '2005-01-01';

(Точный синтаксис SQL зависит от ядра базы данных.)

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

iso_year

Для полей даты и даты / времени - точное совпадение года с номерами недель ISO 8601. Это выражение может сопровождаться другими выражениями поля. Примите год как целое число.

Пример:

Entry.objects.filter(pub_date__iso_year=2005)
Entry.objects.filter(pub_date__iso_year__gte=2005)

(Точный синтаксис SQL зависит от ядра базы данных.)

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

month

Для полей даты и даты / времени - точное совпадение месяца. За этим выражением могут следовать другие выражения поля. Принимает целое число от 1 (январь) до 12 (декабрь).

Пример:

Entry.objects.filter(pub_date__month=12)
Entry.objects.filter(pub_date__month__gte=6)

Эквивалент SQL:

SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6';

(Точный синтаксис SQL зависит от ядра базы данных.)

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

day

Для полей даты и даты / времени - точное совпадение дня. За этим выражением могут следовать другие выражения поля. Примите один день как целое число.

Пример:

Entry.objects.filter(pub_date__day=3)
Entry.objects.filter(pub_date__day__gte=3)

Эквивалент SQL:

SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';

(Точный синтаксис SQL зависит от ядра базы данных.)

Обратите внимание, что это соответствует любому элементу, поле которого pub_date соответствует третьему дню месяца, например 3 января, 3 июля и т. Д.

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

week

Для полей даты и даты / времени возвращает номер недели (1-52 или 53) в соответствии с ISO-8601 , то есть недели начинаются в понедельник, а первая неделя содержит первый четверг недели. 'год.

Пример:

Entry.objects.filter(pub_date__week=52)
Entry.objects.filter(pub_date__week__gte=32, pub_date__week__lte=38)

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

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

week_day

Для полей даты и даты / времени точное совпадение "дня недели". За этим выражением могут следовать другие выражения поля.

Принимает целое число, представляющее день недели, от 1 (воскресенье) до 7 (суббота).

Пример:

Entry.objects.filter(pub_date__week_day=2)
Entry.objects.filter(pub_date__week_day__gte=2)

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

Обратите внимание, что это соответствует любому элементу, в поле которого указан pub_date понедельник (второй день недели), независимо от месяца или года. Дни недели индексируются от 1 (воскресенье) до 7 (суббота).

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

iso_week_day

Новое в Django 3.1.

Для полей date и datetime точное совпадение дня недели ISO 8601. Позволяет связывать дополнительные поиски полей.

Принимает целое число, представляющее день недели от 1 (понедельник) до 7 (воскресенье).

Пример:

Entry.objects.filter(pub_date__iso_week_day=1)
Entry.objects.filter(pub_date__iso_week_day__gte=1)

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

Обратите внимание, что это будет соответствовать любой записи с a, pub_date которая выпадает на понедельник (день 1 недели), независимо от месяца или года, в котором это происходит. Дни недели индексируются: день 1 - понедельник, а день 7 - воскресенье.

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

quarter

Для полей даты и даты / времени соответствие «годовой квартал». За этим выражением могут следовать другие выражения поля. Принимает целое число от 1 до 4, представляющее квартал года.

Пример получения строк для второго квартала (с 1 апреля по 30 июня)

Entry.objects.filter(pub_date__quarter=2)

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

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

time

Для полей даты / времени принудительно устанавливает значение времени. За этим выражением могут следовать другие выражения поля. Принимает значение datetime.time .

Пример:

Entry.objects.filter(pub_date__time=datetime.time(14, 30))
Entry.objects.filter(pub_date__time__range=(datetime.time(8), datetime.time(17)))

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

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

hour

Для полей даты / времени и времени - точное совпадение времени. За этим выражением могут следовать другие выражения поля. Принимает целое число от 0 до 23.

Пример:

Event.objects.filter(timestamp__hour=23)
Event.objects.filter(time__hour=5)
Event.objects.filter(timestamp__hour__gte=12)

Эквивалент SQL:

SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
SELECT ... WHERE EXTRACT('hour' FROM time) = '5';
SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';

(Точный синтаксис SQL зависит от ядра базы данных.)

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

minute

Для полей даты / времени и времени - точное совпадение минут. За этим выражением могут следовать другие выражения поля. Принимает целое число от 0 до 59.

Пример:

Event.objects.filter(timestamp__minute=29)
Event.objects.filter(time__minute=46)
Event.objects.filter(timestamp__minute__gte=29)

Эквивалент SQL:

SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
SELECT ... WHERE EXTRACT('minute' FROM time) = '46';
SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29';

(Точный синтаксис SQL зависит от ядра базы данных.)

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

second

Для полей даты / времени и времени - точное совпадение секунды. За этим выражением могут следовать другие выражения поля. Принимает целое число от 0 до 59.

Пример:

Event.objects.filter(timestamp__second=31)
Event.objects.filter(time__second=2)
Event.objects.filter(timestamp__second__gte=31)

Эквивалент SQL:

SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
SELECT ... WHERE EXTRACT('second' FROM time) = '2';
SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31';

(Точный синтаксис SQL зависит от ядра базы данных.)

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

isnull

Принимает True или False , что соответствует операторам SQL и соответственно .IS NULL IS NOT NULL

Пример:

Entry.objects.filter(pub_date__isnull=True)

Эквивалент SQL:

SELECT ... WHERE pub_date IS NULL;

Не рекомендуется с версии 3.1: Использование небулевых значений в правой части не рекомендуется, используйте вместо них True или False . В Django 4.0 возникнет исключение.

regex

Поиск по регулярному выражению с учетом регистра.

Синтаксис регулярных выражений соответствует используемому ядру базы данных. Для SQLite, который изначально не поддерживает регулярные выражения, эта функциональность обеспечивается определяемой пользователем функцией (Python) REGEXP , поэтому синтаксис регулярных выражений является синтаксисом модуля re Python.

Пример:

Entry.objects.get(title__regex=r'^(An?|The) +')

Эквивалентность в SQL:

SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL

SELECT ... WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c'); -- Oracle

SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL

SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite

Рекомендуется использовать необработанные строки (например, r'foo' вместо 'foo' ) для передачи регулярных выражений.

iregex

Поиск по регулярному выражению без учета регистра.

Пример:

Entry.objects.get(title__iregex=r'^(an?|the) +')

Эквивалентность в SQL:

SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL

SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i'); -- Oracle

SELECT ... WHERE title ~* '^(an?|the) +'; -- PostgreSQL

SELECT ... WHERE title REGEXP '(?i)^(an?|the) +'; -- SQLite

Функции агрегирования

Django предоставляет в модуле следующие агрегатные функции django.db.models . Подробнее об использовании этих функций см. В тематическом руководстве по агрегированию . Обратитесь к документации, Aggregate чтобы узнать, как создавать свои собственные агрегаты.

Предупреждение

SQLite не знает, как управлять агрегатами в полях даты и времени. Причина в том, что в SQLite нет реальных полей даты / времени, а Django в настоящее время эмулирует эти функции с помощью текстового поля. Если вы попытаетесь выполнить агрегирование полей даты / времени с помощью SQLite, вы получите исключение NotImplementedError .

Заметка

Агрегатные функции возвращаются None при использовании с QuerySet пустым объектом . Например, Sum функция агрегирования (сумма) возвращает None вместо, 0 если набор запросов не содержит элемента. Единственным исключением является то Count , что возникает , 0 когда набор запросов пуст.

Все агрегаты имеют следующие параметры:

expressions

Строки, ссылающиеся на поля шаблона или выражения запроса .

output_field

Необязательный параметр, представляющий поле шаблона возвращаемого значения.

Заметка

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

filter

Опция используется для фильтрации строк , которые были объединены.objet Q

Примеры использования см. В разделе « Условное агрегирование и фильтрация в аннотациях» .

**extra

Именованные параметры, которые могут предоставить дополнительный контекст для кода SQL, сгенерированного агрегированием.

Avg

классAvg ( выражение , output_field = None , отличный = False , фильтр = None , ** за дополнительную плату )

Возвращает среднее значение указанного выражения, которое должно иметь числовой тип, если вы не укажете output_field другое поле .

  • Псевдоним по умолчанию: <champ>__avg
  • Тип возвращаемого значения: float если входное значение int , если не идентично начальному полю, или output_field если оно указано

Принимает необязательный параметр:

distinct

Если distinct=True , Avg возвращает среднее значение уникальных значений. Это соответствует коду SQL . По умолчанию это .AVG(DISTINCT <field>) False

Изменено в Django 3.0:

Поддержка distinct=True была добавлена.

Count

classCount ( выражение , отличное = False , filter = None , ** extra )

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

  • Псевдоним по умолчанию: <champ>__count
  • Тип возвращаемого значения: int

Принимает необязательный параметр:

distinct

Да distinct=True , при подсчете учитываются только уникальные экземпляры. Это соответствует коду SQL . По умолчанию это .COUNT(DISTINCT <field>) False

Max

classMax ( выражение , output_field = None , filter = None , ** extra )

Возвращает максимальное значение данного выражения.

  • Псевдоним по умолчанию: <champ>__max
  • Тип возвращаемого значения: идентично начальному полю или output_field если указано

Min

classMin ( выражение , output_field = None , filter = None , ** extra )

Возвращает минимальное значение данного выражения.

  • Псевдоним по умолчанию: <champ>__min
  • Тип возвращаемого значения: идентично начальному полю или output_field если указано

StdDev

classStdDev ( выражение , output_field = None , sample = False , filter = None , ** extra )

Возвращает стандартное отклонение данных, содержащихся в данном выражении.

  • Псевдоним по умолчанию: <champ>__stddev
  • Тип возвращаемого значения: float если входное значение int , если не идентично начальному полю, или output_field если оно указано

Принимает необязательный параметр:

sample

По умолчанию StdDev возвращает стандартное отклонение генеральной совокупности. Однако, если sample=True , возвращаемое значение будет стандартным отклонением выборки.

Sum

классSum ( выражение , output_field = None , отличный = False , фильтр = None , ** за дополнительную плату )

Вычисляет сумму всех значений данного выражения.

  • Псевдоним по умолчанию: <champ>__sum
  • Тип возвращаемого значения: идентично начальному полю или output_field если указано

Принимает необязательный параметр:

distinct

Если distinct=True , Sum возвращает сумму уникальных значений. Это соответствует коду SQL . По умолчанию - False`.SUM(DISTINCT <field>)

Изменено в Django 3.0:

Поддержка distinct=True была добавлена.

Variance

classVariance ( выражение , output_field = None , sample = False , filter = None , ** extra )

Возвращает дисперсию данных данного выражения.

  • Псевдоним по умолчанию: <champ>__variance
  • Тип возвращаемого значения: float если входное значение int , если не идентично начальному полю, или output_field если оно указано

Принимает необязательный параметр:

sample

По умолчанию Variance возвращает дисперсию генеральной совокупности. Однако, если sample=True , возвращаемое значение будет выборкой дисперсии.

Copyright ©2021 All rights reserved