Справочник по 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. Однако сериализация и «рассредоточенная» десериализация содержимого этого атрибута - безопасная (и полностью приемлемая) операция.
API QuerySet
¶
Вот официальное заявление одного из них QuerySet
:
-
class
QuerySet
( 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()
aftervalues()
не имеют смысла, и если вы это сделаете, вы получите исключение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
вызывает исключение для таких дат.
Параметр is_dst
добавлен.
Заметка
Эта функция выполняет преобразование часового пояса непосредственно в базе данных. В результате база данных должна иметь возможность интерпретировать значение tzinfo.tzname(None)
. Это означает следующие требования:
- SQLite: требований нет. Преобразования выполняются на Python с помощью pytz (устанавливается одновременно с Django).
- PostgreSQL: не требуется (см. Часовые пояса ).
- Oracle: не требуется (см. Выбор файла часового пояса ).
- MySQL: загрузка таблиц часовых поясов с помощью mysql_tzinfo_to_sql .
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')
Если необходимо продублировать несколько полей в беспилотной модели, может быть предпочтительнее создать абстрактную модель с общими полями, а затем унаследовать управляемую и беспилотную модели от этой абстрактной модели.
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()
.
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
как приведенный к списку, в том же порядке, как указано.
Добавлена поддержка получения атрибутов первичного ключа в 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')
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
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()
¶
-
classmethod
as_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
запроса.
'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 отложены .
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
¶
Для полей 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
¶
-
class
Count
( выражение , отличное = False , filter = None , ** extra ) ¶ Возвращает количество объектов, связанных с помощью указанного выражения.
- Псевдоним по умолчанию:
<champ>__count
- Тип возвращаемого значения:
int
Принимает необязательный параметр:
-
distinct
¶ Да
distinct=True
, при подсчете учитываются только уникальные экземпляры. Это соответствует коду SQL . По умолчанию это .COUNT(DISTINCT <field>)
False
- Псевдоним по умолчанию:
Max
¶
-
class
Max
( выражение , output_field = None , filter = None , ** extra ) ¶ Возвращает максимальное значение данного выражения.
- Псевдоним по умолчанию:
<champ>__max
- Тип возвращаемого значения: идентично начальному полю или
output_field
если указано
- Псевдоним по умолчанию:
Min
¶
-
class
Min
( выражение , output_field = None , filter = None , ** extra ) ¶ Возвращает минимальное значение данного выражения.
- Псевдоним по умолчанию:
<champ>__min
- Тип возвращаемого значения: идентично начальному полю или
output_field
если указано
- Псевдоним по умолчанию:
StdDev
¶
-
class
StdDev
( выражение , 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
¶
-
class
Variance
( выражение , output_field = None , sample = False , filter = None , ** extra ) ¶ Возвращает дисперсию данных данного выражения.
- Псевдоним по умолчанию:
<champ>__variance
- Тип возвращаемого значения:
float
если входное значениеint
, если не идентично начальному полю, илиoutput_field
если оно указано
Принимает необязательный параметр:
-
sample
¶ По умолчанию
Variance
возвращает дисперсию генеральной совокупности. Однако, еслиsample=True
, возвращаемое значение будет выборкой дисперсии.
- Псевдоним по умолчанию: