QuerySet API¶
Этот раздел описывает QuerySet API. Изложенный материал опирается на материал, изложенный в разделах о моделях и выполнении запросов, возможно вам следует прочитать их перед прочтением этого раздела.
Throughout this reference we’ll use the example Weblog models presented in the database query guide.
Когда вычисляется QuerySets¶
QuerySet может быть создан, отфильтрован, ограничен и использован фактически без выполнения запросов к базе данных. База данных не будет затронута, пока вы не спровоцируете выполнение QuerySet.
QuerySet будет вычислен при таких действиях:
Итерация.
QuerySet– это итератор, и при первом выполнении итерации будет произведен запрос к базе данных. Например, этот код выводит заголовки статей из базы данных:for e in Entry.objects.all(): print(e.headline)
Заметка: не используйте такой подход, если необходимо всего лишь узнать содержит ли результат запроса хотя бы один объект, и вам не нужен сам результат. Эффективнее использовать метод
exists().Ограничение выборки. Как описано в Ограничение выборки, выборка
QuerySetможет быть ограничена, используя синтаксис срезов в Python. Срез не вычисленногоQuerySetобычно возвращает новый не вычисленныйQuerySet, но Django выполнит запрос, если будет указан шаг среза и вернет список. СрезQuerySet, который был вычислен(частично или полностью), также вернет список.Обратите внимание, хотя срез не вычисленного
QuerySetвернет новый не вычисленныйQuerySet, вы не можете изменять (например, добавлять фильтры, менять сортировку) его дальше, т.к. это не транслируется в SQL и не имеет определенного смысла.Pickling/кэширование. Смотрите соответствующий раздел о pickling QuerySets. Основное замечание это то, что при этих операциях будет выполнен запрос к базе данных.
repr().
QuerySetбудет вычислен при вызовеrepr(). Это сделано для удобства использования в консоли Python, вы можете сразу увидеть результат работая сQuerySetв консоли.len().
QuerySetбудет вычислен при выполненииlen()над ним. Как вы и ожидаете будет возвращено количество объектов в результате выборки.Заметка: Не используйте
len()сQuerySetесли вам нужно узнать только количество записей в выборке. Эффективнее использовать подсчет на уровне базы данных, используя оператор SQLSELECT COUNT(*), и Django предоставляет методcount()для этого.list().
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().
Сериализация QuerySets¶
Используя pickle для QuerySet, будет выполнен запрос к базе данных, чтобы загрузить данные в память для сериализации. Сериализация обычно используется перед кэшированием QuerySet или загрузкой из кэша, необходимо, чтобы результат был доступен для использования сразу после загрузки (чтение с базы данных занимает некоторое время, что свело бы всю пользу кэширования к нулю). Это означает что после восстановления сериализованного QuerySet, он будет содержать результат на момент сериализации, а не тот, который хранится в базе данных на текущий момент.
If you only want to pickle the necessary information to recreate the
QuerySet from the database at a later time, pickle the query attribute
of the QuerySet. You can then recreate the original QuerySet (without
any results loaded) using some code like this:
>>> import pickle
>>> query = pickle.loads(s) # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query # Restore the original 'query'.
Атрибут query не является частью публичного API, и является частью внутреннего механизма создания запросов. Однако, поддерживает использование pickle и unpickle как показано в примере выше.
QuerySet API¶
Вот документированное объявление QuerySet:
- class QuerySet(model=None, query=None, using=None, hints=None)¶
Обычно работа с
QuerySetсостоит в использовании цепочек фильтров. Для этого большинство методовQuerySetвозвращает новый «queryset». Эти методы описаны далее.The
QuerySetclass has two public attributes you can use for introspection:- ordered¶
TrueеслиQuerySetиспользует сортировку — то есть использован методorder_by()или модель содержит сортировку по-умолчанию. ИначеFalse.
- db¶
База данных, которая будет использована для выполнения запроса.
Примечание
Параметр
queryдляQuerySetсуществует для того, чтобы специализированные подклассы запросов могли восстанавливать внутреннее состояние запроса. Значение параметра представляет собой непрозрачное представление состояния этого запроса и не является частью общедоступного API.
Методы, которые возвращают новый QuerySets¶
Django предоставляет набор методов QuerySet, которые изменяют возвращаемый результат или выполнение SQL запроса.
filter¶
- filter(**kwargs)¶
Возвращает новый QuerySet содержащий объекты отвечающие параметрам фильтрации.
Параметры фильтрации (**kwargs) должны отвечать формату описанному в соответствующем разделе. Несколько параметров объединяются оператором SQL AND.
If you need to execute more complex queries (for example, queries with OR statements),
you can use Q objects.
exclude¶
- exclude(**kwargs)¶
Возвращает новый QuerySet содержащий объекты не отвечающие параметрам фильтрации.
Параметры фильтрации (**kwargs) должны отвечать формату описанному в соответствующем разделе. Несколько параметров объединяются оператором SQL AND и все это замыкается оператором NOT().
Этот пример исключает все записи с pub_date раньше 3.01.2005 И с 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 раньше 3.01.2005 ИЛИ с 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'
Обратите внимание на второй пример, который больше ограничивает выборку.
If you need to execute more complex queries (for example, queries with OR statements),
you can use Q objects.
annotate¶
- annotate(*args, **kwargs)¶
Добавляет к каждому объекту QuerySet результаты указанных выражений. Выражение может содержать простое значение, указатель на другое поле модели (или связанных моделей), или функции агрегации (среднее, сумма и прочие), которые вычисляются над объектами, связанными с объектами из QuerySet.
Каждый аргумент annotate() добавит аннотацию для каждого объекта, возвращаемого QuerySet.
Функции агрегации описаны в соответствующем разделе ниже.
Аннотация, определенная именованными аргументами, будет использовать имя аргумента, как название аннотации. Для позиционного аргумента будет использовано имя, созданное с названия функции агрегации и используемого поля модели. В позиционных аргументах можно указывать агрегирующее выражение, которое использует только одно поле. Все остальные должны передаваться через именованные аргументы.
For example, if you were manipulating a list of blogs, you may want to determine how many entries have been made in each blog:
>>> 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
The Blog model doesn’t define an entry__count attribute by itself,
but by using a keyword argument to specify the aggregate function, you can
control the name of the annotation:
>>> 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(*fields)¶
По-умолчанию, результат возвращаемый QuerySet, отсортирован по полям указанным в аргументе ordering класса Meta модели. Вы можете переопределить сортировку используя метод 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')
Предупреждение
Сортировка не бесплатная операция. Каждое поле влияет на скорость выполнения запроса. Каждый внешний ключ добавит сортировку по умолчанию связанной модели.
Если в запросе не указан порядок, результаты возвращаются из базы данных в неопределенном порядке. Определенный порядок гарантируется только при упорядочивании по набору полей, которые однозначно идентифицируют каждый объект в результатах. Например, если поле name не уникально, упорядочение по нему не гарантирует, что объекты с одинаковым именем всегда будут отображаться в одном и том же порядке.
reverse¶
- reverse()¶
Используйте метод reverse(), чтобы изменить порядок сортировки на обратный. Вызов reverse() повторно восстановит изначальную сортировку.
Чтобы получить «последние» пять объектов выполните:
my_queryset.reverse()[:5]
Обратите внимание, что это не совсем аналог среза Python с конца. Этот пример вернет сначала последний элемент, потом предпоследний и так далее. Используя список Python и сделав срез seq[-5:], мы увидим пятый элемент с конца первым. Django не поддерживает подобное (срез с конца), т.к. нет способа интерпретировать это в эффективный SQL.
Метод reverse() должен быть вызван для QuerySet с определенной сортировкой (например, при запросе модели с сортировкой по-умолчанию или после использования метода order_by()). Если сортировка не определена , вызов reverse() не будет иметь никакого эффекта.
distinct¶
- distinct(*fields)¶
Возвращает QuerySet с добавленным SELECT DISTINCT в SQL запрос. Повторяющиеся записи будут исключены из результатов запроса.
По-умолчанию, QuerySet не исключает повторяющиеся записи. На практике, это редко является проблемой, простые запросы вроде Blog.objects.all() не создают повторяющиеся записи. Однако, если запрос использует несколько таблиц, возможно что QuerySet вернет повторяющиеся записи. И здесь вам пригодится distinct().
Примечание
Любое поле используемое в order_by() будет добавлено в список выбираемых колонок в части SELECT SQL запроса. Это может привести к непредвиденным результатам если вы используете distinct(). При сортировке по колонке из связанной таблицы, эти колонки будет включены в список выбираемых колонок, что может сделать одинаковые строки результата уникальными. Т.к. эти дополнительные колонки не будет включены в результат(они используются только для определения сортировки), будет выглядеть так, вроде бы distinct() возвращает не уникальные элементы результатов.
Также, если вы используете метод values(), чтобы ограничить выбираемые поля, поля из order_by() (или сортировки по-умолчанию модели) так же будут включены и могут повлиять на уникальность результатов.
Мораль всего этого – будьте осторожны при использовании distinct() и сортировки по полям из связанных моделей. Также, при использовании distinct() и values() вместе, будьте осторожны сортируя по полям не включенным в values().
Только для PostgreSQL можно указать позиционный аргумент (*fields) определяющий для каких полей применять DISTINCT. Они будут добавлены в SELECT DISTINCT ON часть SQL запроса. Вот в чем разница. При обычном вызове distinct(), база данных сравнивает каждое поле каждой строки для определения уникальности записи. При передаче полей в distinct(), база данных будет сравнивать только указанные поля.
Примечание
Если вы указываете поля, вы должны определить и order_by() для QuerySet, и поля в order_by() должны начинаться с полей указанных в distinct(), в том же порядке.
Например, SELECT DISTINCT ON (a) возвращает вам первую запись для каждого уникального значения колонки a. Если вы не определите сортировку, будут возвращены случайные записи для каждого уникального значения.
Examples (those after the first will only work on 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() используется сортировку, которая указана в связанной модели. Возможно вам понадобится явно отсортировать по внешнему ключу, или полю связанной модели, чтобы 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(*fields, **expressions)¶
Возвращает QuerySet , который возвращает словари с результатом вместо объектов моделей.
Каждый словарь представляет объект, ключи которого соответствуют полям модели.
This example compares the dictionaries of values() with the normal model
objects:
# 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'}]>
The values() method also takes optional keyword arguments,
**expressions, which are passed through to annotate():
>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower('name'))
<QuerySet [{'lower_name': 'beatles blog'}]>
You can use built-in and custom lookups in ordering. For example:
>>> 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'}]>
An aggregate within a values() clause is applied before other arguments
within the same values() clause. If you need to group by another value,
add it to an earlier values() clause instead. For example:
>>> 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(), добавьте вvalues()все поля указанные в аргументеselectиспользованном при вызовеextra(). При вызовеextra()послеvalues()все указанные дополнительные поля будут проигнорированы.Вызов
only()иdefer()послеvalues()не имеет смысла, поэтому это вызоветTypeError.Combining transforms and aggregates requires the use of two
annotate()calls, either explicitly or as keyword arguments tovalues(). As above, if the transform has been registered on the relevant field type the firstannotate()can be omitted, thus the following examples are equivalent:>>> 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()), хотя это и не имеет значения. Это ваш шанс проявить индивидуальность.
You can also refer to fields on related models with reverse relations through
OneToOneField, ForeignKey and ManyToManyField attributes:
>>> Blog.objects.values('name', 'entry__headline')
<QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
{'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>
Предупреждение
Так как ManyToManyField и обратная связь может содержать множество связанных записей, выбор этих данных может многократно увеличить размер возвращаемых данных. Это будет особенно заметно, если вы включите несколько таких полей в values(), в таком случае будут возвращены все возможные комбинации значений.
Boolean values for JSONField on SQLite
Due to the way the JSON_EXTRACT SQL function is implemented on SQLite,
values() will return 1 and 0 instead of True and False
for JSONField key transforms.
values_list¶
- values_list(*fields, flat=False, named=False)¶
This is similar to values() except that instead of returning dictionaries,
it returns tuples when iterated over. Each tuple contains the value from the
respective field or expression passed into the values_list() call — so the
first item is the first field, etc. For example:
>>> 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'), ...]>
If you only pass in a single field, you can also pass in the flat
parameter. If True, this will mean the returned results are single values,
rather than one-tuples. An example should make the difference clearer:
>>> 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 будет ошибкой.
You can pass named=True to get results as a
namedtuple():
>>> Entry.objects.values_list('id', 'headline', named=True)
<QuerySet [Row(id=1, headline='First entry'), ...]>
Использование именованного кортежа может сделать результаты более читаемыми за счет небольшого снижения производительности при преобразовании результатов в именованный кортеж.
Если поля не будут указаны при вызове values_list(), будут возвращены все поля модели в порядке, в котором они были объявлены.
A common need is to get a specific field value of a certain model instance. To
achieve that, use values_list() followed by a get() call:
>>> Entry.objects.values_list('headline', flat=True).get(pk=1)
'First entry'
values() и values_list() предназначены для оптимизации для конкретного варианта использования: получения подмножества данных без накладных расходов на создание экземпляра модели. Эта метафора не работает при работе с отношениями «многие-ко-многим» и другими многозначными отношениями (такими как отношение «один-ко-многим» обратного внешнего ключа), поскольку предположение «одна строка, один объект» не выполняется.
For example, notice the behavior when querying across a
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)]>
Авторы с несколькими записями появляются несколько раз, а у авторов без записей в заголовке записи указано «Нет».
Similarly, when querying a reverse foreign key, None appears for entries
not having any author:
>>> Entry.objects.values_list('authors')
<QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]>
Boolean values for JSONField on SQLite
Due to the way the JSON_EXTRACT SQL function is implemented on SQLite,
values_list() will return 1 and 0 instead of True and
False for JSONField key transforms.
dates¶
- dates(field, kind, order='ASC')¶
Возвращает QuerySet, который возвращает список объектов datetime.date, отображающих возможные даты в контексте QuerySet.
field должен быть названием поля DateField вашей модели. kind должен быть "year", "month" или "day". Каждый объект datetime.date - результат «урезания» данных в соответствии с указанным type.
"year"возвращает список уникальных значений года из всех дат указанного поля."month"возвращает список уникальных значений года/месяца из всех дат указанного поля."year"возвращает список уникальных значений года из всех дат указанного поля."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", "day", "hour", "minute" или "second". Каждый объект datetime.datetime результат «урезания» данных в соответствии с указанным kind.
order – сортировка значений. По-умолчанию 'ASC', должна быть 'ASC' или 'DESC'.
tzinfo указывает часовой пояс используемый при создании объектов datetime. Принимает объект datetime.tzinfo. Если передать None, Django использует текущий часовой пояс. Не используется при USE_TZ равном False.
is_dst indicates whether or not pytz should interpret nonexistent and
ambiguous datetimes in daylight saving time. By default (when is_dst=None),
pytz raises an exception for such datetimes.
The is_dst parameter was added.
Примечание
Функция выполняет преобразование даты на уровне базы данных. Поэтому ваша база данных должна понимать значение вида tzinfo.tzname(None). Для этого необходимо:
SQLite: no requirements. Conversions are performed in Python with pytz (installed when you install Django).
PostgreSQL: нет дополнительных требований (смотрите Time Zones).
Oracle: нет дополнительных требований (смотрите Choosing a Time Zone File).
MySQL: установите pytz и загрузите таблицы часовых поясов с помощью mysql_tzinfo_to_sql.
нет()¶
- none()¶
Вызов none() создаст набор запросов, который никогда не возвращает никаких объектов, и при доступе к результатам не будет выполняться никакой запрос. Набор запросов qs.none() является экземпляром EmptyQuerySet.
Например:
>>> Entry.objects.none()
<QuerySet []>
>>> from django.db.models.query import EmptyQuerySet
>>> isinstance(Entry.objects.none(), EmptyQuerySet)
True
все()¶
- all()¶
Возвращает копию текущего QuerySet (или подкласса QuerySet). Это может быть полезно, если вам нужно передать в функцию менеджер модели или QuerySet и выполнить дальнейшую фильтрацию результата. После вызова all() вы получите копию QuerySet, которую можно передать в функцию не боясь, что она изменит текущий QuerySet.
Если QuerySet был выполнен, он кэширует результат. Если данные в базе данных поменялись после выполнения QuerySet, вы можете получить обновленный результат запроса, вызывав all() уже выполненного QuerySet.
using¶
- union(*other_qs, all=False)¶
Использует оператор SQL UNION для объединения результатов двух или более наборов QuerySet. Например:
>>> qs1.union(qs2, qs3)
Оператор UNION по умолчанию выбирает только отдельные значения. Чтобы разрешить дублирование значений, используйте аргумент all=True.
union(), intersection(), and difference() return model instances
of the type of the first QuerySet even if the arguments are QuerySets
of other models. Passing different models works as long as the SELECT list
is the same in all QuerySets (at least the types, the names don’t matter
as long as the types are in the same order). In such cases, you must use the
column names from the first QuerySet in QuerySet methods applied to the
resulting QuerySet. For example:
>>> qs1 = Author.objects.values_list('name')
>>> qs2 = Entry.objects.values_list('headline')
>>> qs1.union(qs2).order_by('name')
In addition, only LIMIT, OFFSET, COUNT(*), ORDER BY, and
specifying columns (i.e. slicing, count(), order_by(), and
values()/values_list()) are allowed on the resulting
QuerySet. Further, databases place restrictions on what operations are
allowed in the combined queries. For example, most databases don’t allow
LIMIT or OFFSET in the combined queries.
iterator¶
- intersection(*other_qs)¶
Использует оператор SQL INTERSECT для возврата общих элементов двух или более наборов QuerySet. Например:
>>> qs1.intersection(qs2, qs3)
См. некоторые ограничения в union().
defer¶
- difference(*other_qs)¶
Uses SQL’s EXCEPT operator to keep only elements present in the
QuerySet but not in some other QuerySets. For example:
>>> qs1.difference(qs2, qs3)
См. некоторые ограничения в union().
**extra¶
- extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)¶
Иногда, стандартных возможностей Django не хватает для создания сложного условия WHERE запроса. Для таких случаев, Django предоставляет метод extra() QuerySet — метод позволяющий изменять SQL сгенерированный QuerySet.
Используйте этот метод в крайнем случае
Это старый API, который мы собираемся удалить в будущем. Используйте его, только если другие методы QuerySet вам не помогают. Если вам пришлось использовать этот метод, просим создать «тикет», используя тег QuerySet.extra, и описать ваш случай (просим для начала ознакомиться с существующим списком случаев), чтобы мы могли улучшить QuerySet API, и удалить extra(). Мы больше не улучшаем и не исправляем ошибки для этого метода.
For example, this use of 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 при необходимости. Главный минус – если вы будете использовать метку какой-то таблицы из QuerySet в SQL, возможен случай, когда Django может изменить эту метку (например, если QuerySet используется как под-запрос в другом запросе).
Предупреждение
Вы должны быть предельно осторожны при использовании extra(). Необходимо экранировать все аргументы с помощью params, которые передает пользователь, чтобы избежать SQL-инъекций. Смотрите раздел о защите от SQL-инъекций.
Вы также не должны заключать в кавычки заполнители в строке SQL. Этот пример уязвим для SQL-инъекций из-за кавычек вокруг %s:
SELECT col FROM sometable WHERE othercol = '%s' # unsafe!
Вы можете узнать больше о том, как работает Защита от SQL-инъекций в Django.
По определению, дополнительные параметры поиска определенные в 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;
Note that the parentheses required by most database engines around subqueries are not required in Django’s
selectclauses. Also note that some database backends, such as some MySQL versions, don’t support subqueries.В некоторых редких случаях вам может потребоваться передать параметры фрагментам SQL в
extra(select=...). Для этой цели используйте параметр select_params.Например:
Blog.objects.extra( select={'a': '%s', 'b': '%s'}, select_params=('one', 'two'), )
Если вам необходимо использовать
%sв запрашиваемой строке, используйте%%s.where/tablesВы можете добавить оператор SQL
WHERE— возможно для выполнения не явного объединения таблиц — by usingwhere. Используя параметрtablesможно добавить таблицы в оператор SQLFROM.whereиtablesпринимают список строк. Все параметрыwhereбудут добавлены к остальным критериям через оператор «AND» .Например:
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таблиц, которые уже используются запросом. В таком случае Django предполагает, что вы хотите добавить их повторно. Это создает проблему, т.к. таблица будет добавлена с псевдонимом(an alias). Если таблица несколько раз используется в запросе, второй и последующие вхождения должны использовать псевдонимы, чтобы база данных могла различить их. При обращении к добавленной таблице в параметреwhereвы получите ошибку.Скорее всего вы будете использовать дополнительные таблицы, которые еще не добавлены в запрос. Однако, если все таки возникнет описанная выше ситуация, существует несколько способов ее решить. Первый, посмотрите возможно ли использовать уже добавленную в запрос таблицу. Если это не возможно, используйте вызов
extra()в начале конструкции запроса, чтобы ваша таблица использовалась первой. В конце концов, если каким-то образом все остальное вам не помогло, посмотрите на созданный запрос и перепишите параметрwhereтаким образом, чтобы использовался псевдоним назначенный дополнительной таблице. При одинаковом способе создать запрос псевдоним будет всегда не измененным.order_byЕсли вам необходимо отсортировать полученный
QuerySetиспользуя новые поля или таблицы, которые вы добавили черезextra(), используйте параметрorder_byпередав последовательность строк. Эти строки должны быть полями модели (как и в обычном методеorder_by()), в форматеtable_name.column_nameили псевдонимы колонок которые вы указали в параметре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это список дополнительных параметров, которые будут подставлены в условиеwhere.Например:
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 преобразует все значения поля в число перед сравнением. Например, если таблица содержит значения 'abc', 'def' и в запросе WHERE mycolumn=0, обе строки попадут в результат. Чтобы избежать этого, используйте значение правильного типа в запросе.
defer¶
- defer(*fields)¶
При сложной структуре данных модели могут содержать большое количество полей, некоторые из которых могут содержать большие объемы данных(например, текстовые поля), или использовать ресурсоемкий процесс преобразования данных в объекты 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)
Некоторые поля всегда будут выбираться из базы данных, даже если вы их добавите в вызов defer(). Всегда выбирается первичный ключ. Используя select_related() для получения связанных моделей, не «откладывайте» загрузку связывающего поля иначе получите ошибку.
Примечание
Метод defer() (и его «коллега» only()) предназначены только для опытных пользователей. Они предоставляют возможность оптимизировать запрос. Но для начала вам следует проанализировать его, точно определить какие данные вам необходимы и удостовериться, что разница между получением всех полей и получением определенных, будет значительной.
Even if you think you are in the advanced use-case situation, only use
defer() when you cannot, at queryset load time, determine if you will need
the extra fields or not. If you are frequently loading and using a
particular subset of your data, the best choice you can make is to
normalize your models and put the non-loaded data into a separate model
(and database table). If the columns must stay in the one table for some
reason, create a model with Meta.managed = False (see the
managed attribute documentation)
containing just the fields you normally need to load and use that where you
might otherwise call defer(). This makes your code more explicit to the
reader, is slightly faster and consumes a little less memory in the Python
process.
Например, обе эти модели используют одну таблицу в базе данных:
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(*fields)¶
The only() method is more or less the opposite of defer(). You call
it with the fields that should not be deferred when retrieving a model. If
you have a model where almost all the fields need to be deferred, using
only() to specify the complementary set of fields can result in simpler
code.
Например, у вас есть модель с полями 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(). Используйте его с осторожностью и только в отсутствии других вариантов.
Using only() and omitting a field requested using select_related()
is an error as well.
using¶
- using(alias)¶
Этот метод контролирует какую базу данных будет использовать 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=())¶
Возвращает QuerySet, блокирующий записи до завершения транзакции, используя оператор 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:
...
Все, удовлетворяющие фильтрам, строки будут заблокированы до завершения транзакции, то есть другие транзакции не смогут изменить или заблокировать это строки.
Обычно, если другая транзакция заблокировала одну из выбранных записей, запрос будет заблокирован до снятия блокировки. Если вы не желаете этого, используйте select_for_update(nowait=True). Вызов будет не блокированным, если записи уже заблокированы, будет вызвано исключение DatabaseError при вычислении QuerySet.
По умолчанию select_for_update() блокирует все строки, выбранные запросом. Например, строки связанных объектов, указанные в select_related(), блокируются в дополнение к строкам модели набора запросов. Если это нежелательно, укажите связанные объекты, которые вы хотите заблокировать, в select_for_update(of=(...)), используя тот же синтаксис полей, что и select_based(). Используйте значение self для ссылки на модель набора запросов.
Заблокируйте родительские модели в select_for_update(of=(...))
Если вы хотите заблокировать родительские модели при использовании многотабличного наследования <multi-table-inheritance>`, вы должны указать поля родительских ссылок (по умолчанию <parent_model_name>_ptr) в аргументе of. Например:
Restaurant.objects.select_for_update(of=('self', 'place_ptr'))
You can’t use select_for_update() on nullable relations:
>>> 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
To avoid that restriction, you can exclude null objects if you don’t care about them:
>>> Person.objects.select_related('hometown').select_for_update().exclude(hometown=None)
<QuerySet [<Person: ...)>, ...]>
Currently, the postgresql, oracle, and mysql database
backends support select_for_update(). However, MariaDB 10.3+ supports only
the nowait argument and MySQL 8.0.1+ supports the nowait and
skip_locked arguments. MySQL and MariaDB don’t support the of argument.
Passing nowait=True, skip_locked=True, or of to
select_for_update() using database backends that do not support these
options, such as MySQL, raises a NotSupportedError. This
prevents code from unexpectedly blocking.
Выполнение выборки с select_for_update() в autocommit режиме для бэкенда, который поддерживает SELECT ... FOR UPDATE, вызовет TransactionManagementError т.к. строки не будут заблокированы в этом случае. Если разрешить такое выполнение, это может привести к повреждению данных т.к. код рассчитывает, что будет выполнен в транзакции, хотя это не так.
Использование select_for_update() с базой данных, которая не поддерживает SELECT ... FOR UPDATE (например, SQLite) не будет иметь никакого эффекта. SELECT ... FOR UPDATE не будет добавлено к запросу, и ошибка не будет вызвана, если select_for_update() используется в autocommit режиме.
Предупреждение
Хотя select_for_update() вызывает ошибку в autocommit режиме, т.к. TestCase автоматически использует транзакцию для каждого теста, вызов select_for_update() в TestCase даже вне блока atomic() будет выполнен без ошибки TransactionManagementError. Для правильного тестирования select_for_update() используйте TransactionTestCase.
Некоторые выражения могут не поддерживаться
PostgreSQL не поддерживает select_for_update() с выражениями Window.
сырой()¶
- raw(raw_query, params=None, translations=None)¶
Принимает SQL запрос, выполняет его и возвращает объект django.db.models.query.RawQuerySet. Этот объект RawQuerySet может быть проитерирован как и обычный QuerySet для получения объектов результата.
Смотрите Использование чистого SQL.
Предупреждение
raw() всегда выполняет новый запрос к базе данных и игнорирует предыдущую фильтрацию. Поэтому следует вызывать его из Manager или чистого объекта QuerySet.
Методы, которые возвращают новый QuerySets¶
Комбинированные наборы запросов должны использовать одну и ту же модель.
И (&)¶
Combines two QuerySets using the SQL AND operator.
Можно использовать такой запрос:
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
Методы, которые не возвращают QuerySets¶
Следующие методы выполняют QuerySet и возвращают не QuerySet.
Эти методы не используют кэш (смотрите Кэширование и QuerySets) и выполняют запрос к базе данных при каждом вызове.
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(defaults=None, **kwargs)¶
Удобный метод для поиска объекта по заданным параметрам поиска kwargs (может быть пустым, если все поля содержат значения по умолчанию), и создания нового при необходимости.
Возвращает кортеж (object, created), где object полученный или созданный объект и created – булево значение, указывающее был ли создан объект.
Это предназначено для предотвращения создания дублирующихся объектов при параллельных запросах и в качестве ярлыка для шаблонного кода. Например:
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()
Такой способ становится весьма громоздким при увеличении количества полей модели. Пример выше может быть переписан с использованием метода 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), этот метод склонен к «гонке-состояний» и в БД могут попасть не уникальные данные(прим. пер. - Django то проверить уникальность, но при нескольких процессах запросы могут одновременно отправиться на выполнения к БД, а там уже ничего не проверяется).
Вы можете указать более сложные условия для полученного объекта, связав get_or_create() с filter() и используя 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() — кроме одного не обязательного defaults — будут использованы при вызове get(). Если объект найден, get_or_create() вернет этот объект и False. Если найдено несколько объектов - будет вызвано исключение 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 и вы хотите использовать его в параметрах поиска в get_or_create(), просто используйте 'defaults__exact':
Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})
Метод get_or_create() использует аналогичное поведение с ошибками что и метод create(), если вы самостоятельно определяете значение первичного ключа. Если объект должен быть создан и значение первичного ключа уже существует в базе данных, будет вызвано исключение IntegrityError.
Finally, a word on using get_or_create() in Django views. Please make sure
to use it only in POST requests unless you have a good reason not to.
GET requests shouldn’t have any effect on data. Instead, use POST
whenever a request to a page has a side effect on your data. For more, see
Safe methods in the HTTP spec.
Предупреждение
Вы можете использовать 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)
You can use get_or_create() through Book’s chapters field, but it only
fetches inside the context of that 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
Это произошло, потому что мы пытались получить или создать «Chapter 1» для книги «Ulysses», но ни один объект не был найден, т.к. он не связан с этой книгой, и мы получили ошибку при попытке его создать т.к. поле title должно быть уникальным.
update_or_create¶
- update_or_create(defaults=None, **kwargs)¶
A convenience method for updating an object with the given kwargs, creating
a new one if necessary. The defaults is a dictionary of (field, value)
pairs used to update the object. The values in defaults can be callables.
Возвращает кортеж (object, created), где object полученный или обновленный объект и created – булево значение, указывающее был ли создан объект.
Метод 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'},
)
For detailed description how names passed in kwargs are resolved see
get_or_create().
Как описано выше в get_or_create(), этот метод подвержен состоянию гонки, что может привести к созданию одинаковых строк в базе данных, если уникальность полей не контролируется на уровне базы данных.
Метод get_or_create() использует аналогичное поведение с ошибками что и метод create(), если вы самостоятельно определяете значение первичного ключа. Если объект должен быть создан и значение первичного ключа уже существует в базе данных, будет вызвано исключение IntegrityError.
bulk_create¶
- bulk_create(objs, batch_size=None, ignore_conflicts=False)¶
This method inserts the provided list of objects into the database in an efficient manner (generally only 1 query, no matter how many objects there are):
>>> Entry.objects.bulk_create([
... Entry(headline='This is a test'),
... Entry(headline='This is only a test'),
... ])
Следует упомянуть ряд оговорок:
Метод модели
save()не будет вызван, и сигналыpre_saveиpost_saveне будут вызваны.Не работает с дочерними моделями при multi-table наследовании.
If the model’s primary key is an
AutoField, the primary key attribute can only be retrieved on certain databases (currently PostgreSQL and MariaDB 10.5+). On other databases, it will not be set.Не работает со связями многое-ко-многим.
Он преобразует
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.
On databases that support it (all but Oracle), setting the ignore_conflicts
parameter to True tells the database to ignore failure to insert any rows
that fail constraints such as duplicate unique values. Enabling this parameter
disables setting the primary key on each model instance (if the database
normally supports it).
Предупреждение
В MySQL и MariaDB установка параметра «ignore_conflicts» в значение «True» превращает определенные типы ошибок, кроме дублирующегося ключа, в предупреждения. Даже в строгом режиме. Например: недопустимые значения или нарушения, не допускающие значения NULL. Дополнительную информацию см. в документации MySQL и документации MariaDB.
Returns objs as cast to a list, in the same order as provided.
Support for the fetching primary key attributes on MariaDB 10.5+ was added.
update¶
- bulk_update(objs, fields, batch_size=None)¶
This method efficiently updates the given fields on the provided model instances, generally with one query:
>>> 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.Обновление полей, определенных в предках многотабличного наследования, потребует дополнительного запроса для каждого предка.
Если отдельный пакет содержит дубликаты, только первый экземпляр в этом пакете приведет к обновлению.
Параметр batch_size указывает количество объектов, которые будут созданы за один запрос. По умолчанию все объекты создаются одним запросом, кроме SQLite, где есть ограничение на количество переменных в запросе равное 999.
count¶
- count()¶
Возвращает количество записей в базе данных отвечающем запросу QuerySet. Метод count() никогда не вызывает исключение.
Например:
# 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() использует SELECT COUNT(*), так что всегда используйте метод count() вместо загрузки всех записей в объекты Python и вызов len() над результатом (если вам кончено в любом случае не понадобится загружать их далее, в таком случае len() будет быстрее).
Обратите внимание, если вам необходимо количество объектов в QuerySet и сами объекты (например, цикл по ним), возможно эффективнее использовать len(queryset), чтобы избежать дополнительного запроса при выполнении count().
in_bulk¶
- in_bulk(id_list=None, *, field_name='pk')¶
Takes a list of field values (id_list) and the field_name for those
values, and returns a dictionary mapping each value to an instance of the
object with the given field value. If id_list isn’t provided, all objects
in the queryset are returned. field_name must be a unique field, and it
defaults to the primary key.
Например:
>>> 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)¶
Evaluates the QuerySet (by performing the query) and returns an iterator
(see PEP 234) over the results. A QuerySet typically caches its results
internally so that repeated evaluations do not result in additional queries. In
contrast, iterator() will read results directly, without doing any caching
at the QuerySet level (internally, the default iterator calls iterator()
and caches the return value). For a QuerySet which returns a large number of
objects that you only need to access once, this can result in better
performance and a significant reduction in memory.
Заметим, что использование iterator() для QuerySet, который уже был вычислен, приведет к повторному вычислению и выполнению запроса к базе данных.
Also, use of iterator() causes previous prefetch_related() calls to be
ignored since these two optimizations do not make sense together.
В зависимости от серверной части базы данных результаты запроса будут либо загружены все сразу, либо переданы из базы данных с помощью курсоров на стороне сервера.
С курсорами на стороне сервера¶
Oracle и PostgreSQL <postgresql-server-side-cursors> используют серверные курсоры для потоковой передачи результатов из базы данных без загрузки всего набора результатов в память.
Драйвер базы данных Oracle всегда использует курсоры на стороне сервера.
Для курсоров на стороне сервера параметр chunk_size определяет количество результатов, которые необходимо кэшировать на уровне драйвера базы данных. Извлечение больших фрагментов уменьшает количество обращений между драйвером базы данных и базой данных за счет памяти.
В PostgreSQL курсоры на стороне сервера будут использоваться только в том случае, если для параметра DISABLE_SERVER_SIDE_CURSORS установлено значение False. Прочтите Пул транзакций и курсоры на стороне сервера, если вы используете пул соединений, настроенный в режиме пула транзакций. Когда курсоры на стороне сервера отключены, поведение такое же, как и в базах данных, которые не поддерживают курсоры на стороне сервера.
Без серверных курсоров¶
MySQL не поддерживает потоковую передачу результатов, поэтому драйвер базы данных Python загружает весь набор результатов в память. Результирующий набор затем преобразуется в объекты строк Python адаптером базы данных с использованием метода fetchmany(), определенного в PEP 249.
SQLite может получать результаты пакетно, используя fetchmany(), но поскольку SQLite не обеспечивает изоляцию между запросами внутри соединения, будьте осторожны при записи в итерируемую таблицу. См. Изоляция при использовании QuerySet.iterator() для получения дополнительной информации.
Параметр chunk_size управляет размером пакетов, которые Django получает из драйвера базы данных. Большие пакеты уменьшают затраты на взаимодействие с драйвером базы данных за счет небольшого увеличения потребления памяти.
The default value of chunk_size, 2000, comes from a calculation on the
psycopg mailing list:
Если предположить, что строки состоят из 10–20 столбцов и содержат текстовые и числовые данные, 2000 будет извлекать менее 100 КБ данных, что кажется хорошим компромиссом между количеством передаваемых строк и количеством данных, отбрасываемых в случае досрочного выхода из цикла.
latest¶
- latest(*fields)¶
Возвращает последний объект, используя значение из поля даты указанного параметром field_name.
Этот пример возвращает последний объект Entry в таблице по полю pub_date:
Entry.objects.latest('pub_date')
Вы также можете выбрать последнюю версию на основе нескольких полей. Например, чтобы выбрать Запись с самой ранней expire_date, когда две записи имеют одинаковую pub_date:
Entry.objects.latest('pub_date', '-expire_date')
Знак минус в '-expire_date' означает сортировку expire_date в нисходящем порядке. Поскольку latest() получает последний результат, выбирается Entry с самой ранней expire_date.
Если в Meta модели определен get_latest_by, вы можете не указывать аргумент field_name при вызове earliest() или latest(). Django будет использовать поле указанное в get_latest_by как значение по-умолчанию.
Как и get(), earliest() и latest() вызывает исключение DoesNotExist, если объект не найден.
Заметим что earliest() и latest() существует исключительно для удобства и читаемости.
Заметим что earliest() и latest() существует исключительно для удобства и читаемости.
Поскольку порядок делегируется базе данных, результаты в полях, допускающих значения NULL, могут быть упорядочены по-разному, если вы используете разные базы данных. Например, PostgreSQL и MySQL сортируют нулевые значения, как если бы они были выше, чем ненулевые значения, а SQLite делает обратное.
Возможно, вы захотите отфильтровать нулевые значения:
Entry.objects.filter(pub_date__isnull=False).latest('pub_date')
earliest¶
- earliest(*fields)¶
Работает как и latest() только наоборот.
first¶
- first()¶
Возвращает первый объект из выборки, или None если ничего не найдено. Если для QuerySet не указана сортировка, он будет отсортирован по первичному ключу.
Например:
p = Article.objects.order_by('title', 'pub_date').first()
first() создан просто для удобства и аналогичен следующему коду:
try:
p = Article.objects.order_by('title', 'pub_date')[0]
except IndexError:
p = None
последний()¶
- last()¶
Работает как и first(), но возвращает последний объект из выборки.
aggregate¶
- aggregate(*args, **kwargs)¶
Возвращает словарь агрегированных значений (среднее значение, сума и др.) вычисленных для QuerySet. Каждый аргумент aggregate() определяет значение, которые будет включено в возвращаемый словарь.
Функции агрегации Django описаны в Функции агрегации. Так как они являются выражениями запроса, вы можете комбинировать функции агрегации друг с другом или значениями, чтобы создать сложные агрегации.
Агрегация, указанная с помощью именованного аргумента, использует имя аргумента как название ключа в возвращаемом словаре. Для анонимных аргументов названия ключей будут созданы из названия функции агрегации и названия поля модели используемого в агрегации данных. Сложные агрегации не могут использовать анонимные аргументы и вы должны указать именованные.
For example, when you are working with blog entries, you may want to know the number of authors that have contributed blog entries:
>>> from django.db.models import Count
>>> q = Blog.objects.aggregate(Count('entry'))
{'entry__count': 16}
By using a keyword argument to specify the aggregate function, you can control the name of the aggregation value that is returned:
>>> q = Blog.objects.aggregate(number_of_entries=Count('entry'))
{'number_of_entries': 16}
Для углубленного изучения агрегации смотрите раздел про агрегацию.
exists¶
- exists()¶
Возвращает True если QuerySet содержит какой-либо результат, иначе - False. Выполняет на столько простой и быстрый запрос, на сколько это возможно, почти идентичный обычному запросу QuerySet.
exists() is useful for searches relating to both
object membership in a QuerySet and to the existence of any objects in
a QuerySet, particularly in the context of a large QuerySet.
The most efficient method of finding whether a model with a unique field
(e.g. primary_key) is a member of a QuerySet is:
entry = Entry.objects.get(pk=123)
if some_queryset.filter(pk=entry.pk).exists():
print("Entry contained in queryset")
Which will be faster than the following which requires evaluating and iterating through the entire queryset:
if entry in some_queryset:
print("Entry contained in QuerySet")
And to find whether a queryset contains any items:
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 не был еще вычислен, но вы точно знаете что будет вычислен в любом случае, тогда вызов some_query_set.exists() выполнит больше работы (один запрос для проверки наличия данных и один для получения данных) чем просто bool(some_queryset), который получит результат и проверит не пустой ли он.
update¶
- update(**kwargs)¶
Выполняет SQL запрос, обновляющий данные указанных полей и возвращает количество измененных записей(которое может быть не равно количеству обновленных записей, если некоторые из них уже содержали новое значение).
For example, to turn comments off for all blog entries published in 2010, you could do this:
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
(Пример подразумевает что модель Entry содержит поля pub_date и comments_on.)
You can update multiple fields — there’s no limit on how many. For example,
here we update the comments_on and headline fields:
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False, headline='This is old')
The update() method is applied instantly, and the only restriction on the
QuerySet that is updated is that it can only update columns in the
model’s main table, not on related models. You can’t do this, for example:
>>> Entry.objects.update(blog__name='foo') # Won't work!
Filtering based on related fields is still possible, though:
>>> Entry.objects.filter(blog__id=1).update(comments_on=True)
Метод update() не может быть вызван для QuerySet с примененным срезом, или который не может быть отфильтрован по какой-либо другой причине.
The update() method returns the number of affected rows:
>>> 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)
Использование 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, к которому был применен срез или который не может быть отфильтрован по любой другой причине.
For example, to delete all the entries in a particular blog:
>>> 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})
By default, Django’s ForeignKey emulates the SQL
constraint ON DELETE CASCADE — in other words, any objects with foreign
keys pointing at the objects to be deleted will be deleted along with them.
For example:
>>> 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 не мешают быстрому удалению.
Заметим, что запросы, созданные при удалении объектов не обсуждаются т.к. являются деталями реализации Django.
as_manager¶
- classmethod as_manager()¶
Метод класса, который возвращает экземпляр Manager, который содержит копию методов QuerySet. Смотрите Создание Manager с методами QuerySet.
**extra¶
- explain(format=None, **options)¶
Возвращает строку плана выполнения QuerySet, в которой подробно описано, как база данных будет выполнять запрос, включая любые индексы или соединения, которые будут использоваться. Знание этих деталей может помочь вам повысить производительность медленных запросов.
For example, when using 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, поскольку реализация там непроста.
Параметр format изменяет выходной формат базы данных по умолчанию, который обычно является текстовым. PostgreSQL поддерживает форматы «TEXT», «JSON», «YAML» и «XML». MariaDB и MySQL поддерживают форматы «ТЕКСТ» (также называемый «ТРАДИЦИОННЫЙ») и «JSON». MySQL 8.0.16+ также поддерживает улучшенный формат TREE, который похож на вывод TEXT в PostgreSQL и используется по умолчанию, если поддерживается.
Some databases accept flags that can return more information about the query. Pass these flags as keyword arguments. For example, when using PostgreSQL:
>>> print(Blog.objects.filter(title='My Blog').explain(verbose=True, analyze=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.
Support for the 'TREE' format on MySQL 8.0.16+ and analyze option
on MariaDB and MySQL 8.0.18+ were added.
Операторы фильтрации¶
Операторы фильтрации используются для создания оператора WHERE в SQL. Они используются как именованные аргументы для методов QuerySet: filter(), exclude() и get().
Введение смотрите в разделе о моделях и выполнении запросов к базе данных.
Встроенные операторы фильтрации представлены ниже. Также можно создать собственный фильтр для поля модели.
По умолчанию, если тип фильтра явно не указан (например, Entry.objects.get(id=14)), подразумевается exact.
select¶
Точное совпадение. Если передано значение None, оно будет интерпретировано как SQL NULL (смотрите подробности в описании 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, настройка «collation» таблицы базы данных определяет будет ли использовано регистрозависимое сравнение для exact. Это настройка базы данных, не Django. Можно настроить регистрозависимое сравнение для таблиц MySQL. Подробности смотрите в разделе о сравнении документации о базах данных.
iexact¶
Точное совпадение, регистро-независимое. Если передано значение None, оно будет интерпретировано как SQL NULL (смотрите подробности в описании 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 и Unicode (не-ASCII) строки, помните замечание о сравнении строк в SQLite. SQLite не выполняет регистронезависимое сравнение Unicode строк.
contains¶
Регистрозависимая проверка на вхождение.
Например:
Entry.objects.get(headline__contains='Lennon')
Аналог SQL:
SELECT ... WHERE headline LIKE '%Lennon%';
Заметим, что будет найдена строка 'Lennon honored today', но не 'lennon honored today'.
Пользователям SQLite
SQLite не поддерживает регистрозависимый оператор LIKE; contains работает так же как и icontains для SQLite. Смотрите замечание о сравнении строк в SQLite.
icontains¶
Регистронезависимая проверка на вхождение.
Например:
Entry.objects.get(headline__icontains='Lennon')
Аналог SQL:
SELECT ... WHERE headline ILIKE '%Lennon%';
Пользователям SQLite
Используя SQLite и Unicode (не-ASCII) строки, помните замечание о сравнении строк в SQLite.
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');
Вы можете также передать QuerySet для получения списка значений:
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, чтобы спровоцировать выполнение запроса. Без этого, он будет использован как подзапрос т.к. QuerySets – ленивы.
гт¶
Больше чем.
Например:
Entry.objects.filter(id__gt=4)
Аналог SQL:
SELECT ... WHERE id > 4;
гте¶
Больше чем или равно.
л¶
Меньше чем.
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 и Unicode (не-ASCII) строки, помните замечание о сравнении строк в SQLite.
endswith¶
Регистрозависимая проверка оканчивается ли поле с указанного значения.
Например:
Entry.objects.filter(headline__endswith='Lennon')
Аналог SQL:
SELECT ... WHERE headline LIKE '%Lennon';
Пользователям SQLite
SQLite не поддерживает регистрозависимый оператор LIKE; endswith работает так же как и iendswith для SQLite. Смотрите замечание о сравнении строк в SQLite.
iendswith¶
Регистронезависимая проверка оканчивается ли поле с указанного значения.
Например:
Entry.objects.filter(headline__iendswith='Lennon')
Аналог SQL:
SELECT ... WHERE headline ILIKE '%Lennon'
Пользователям SQLite
Используя SQLite и Unicode (не-ASCII) строки, помните замечание о сравнении строк в SQLite.
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 по датам не включит записи последнего дня, так как границы интерпретируются как «00:00 указанного дня». Если pub_date было DateTimeField, мы бы получили следующий SQL запрос:
SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';
В общем вы не можете использовать date и datetime вместе.
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, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
year¶
Проверка года для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает числовое значение года.
Например:
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, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
year¶
Проверка года для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает числовое значение года.
Например:
Entry.objects.filter(pub_date__iso_year=2005)
Entry.objects.filter(pub_date__iso_year__gte=2005)
(Точный синтаксис SQL зависит от базы данных.)
При USE_TZ равном True, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
month¶
Проверка месяца для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает целое число от 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, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
день¶
Проверка дня месяца для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает номер дня месяца.
Например:
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-го января, 3-го июля и тд.
При USE_TZ равном True, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
week_day¶
Для полей даты и даты и времени верните номер недели (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, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
week_day¶
Проверка дня недели для полей date/datetime. Позволяет использовать дополнительные проверки поля.
Принимает номер дня недели от 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, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
iso_week_day¶
Для полей даты и даты и времени точное соответствие дня недели ISO 8601. Позволяет связывать дополнительные поиски по полям.
Принимает целочисленное значение, представляющее день недели от 1 (понедельник) до 7 (воскресенье).
Например:
Entry.objects.filter(pub_date__iso_week_day=1)
Entry.objects.filter(pub_date__iso_week_day__gte=1)
(Аналог SQL не представлен т.к. реализация отличается для различных баз данных.)
Обратите внимание, что это будет соответствовать любой записи с pub_date, выпадающей на понедельник (первый день недели), независимо от месяца или года, в котором это происходит. Дни недели индексируются: день 1 — понедельник, день 7 — воскресенье.
При USE_TZ равном True, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
четверть¶
Проверка года для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает числовое значение года.
Пример получения записей за второй квартал (с 1 апреля по 30 июня):
Entry.objects.filter(pub_date__quarter=2)
(Аналог SQL не представлен т.к. реализация отличается для различных баз данных.)
При USE_TZ равном True, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
datetimes¶
Для поля даты и времени преобразует значение в дату. Позволяет использовать дополнительные проверки поля. Принимает дату.
Например:
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, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
hour¶
Проверка часа для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает число от 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, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
minute¶
Проверка минуты для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает целое число от 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, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
second¶
Проверка секунды для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает целое число от 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, значение поля datetime будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.
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: Using non-boolean values as the right-hand side is deprecated, use True
or False instead. In Django 4.0, the exception will be raised.
regex¶
Регистрозависимая проверка регулярным выражением.
Синтаксис регулярных выражений зависит от базы данных. Для SQLite, который не поддерживает регулярные выражения, эта функция обеспечена на уровне Python, поэтому используется синтаксис модуля Python re.
Например:
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
Рекомендуется использовать «raw» строки (например, 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 вызовут ошибку NotSupportedError.
Note
Aggregation functions return None when used with an empty
QuerySet. For example, the Sum aggregation function returns None
instead of 0 if the QuerySet contains no entries. An exception is
Count, which does return 0 if the QuerySet is empty.
Функции агрегации обычно принимают следующие параметры:
expression¶
Strings that reference fields on the model, or query expressions.
output_field¶
Необязательный аргумент, который определяет поле модели результата.
Примечание
При использовании нескольких полей Django может определить output_field в том случае, если все поля одного типа. Иначе необходимо явно указать output_field.
filter¶
Необязательный Q-объект, который используется для фильтрации агрегируемых строк.
См. примеры использования в условной агрегации и фильтрации по аннотациям.
**extra¶
Именованные аргументы, которая указывают дополнительный контекст для SQL, созданного для агрегации.
Среднее¶
- class Avg(expression, output_field=None, distinct=False, filter=None, **extra)¶
Возвращает среднее значение указанного выражения, которое должно быть численным, если только вы не указали другой
output_field..Псевдоним по-умолчанию:
<field>__avgReturn type:
floatif input isint, otherwise same as input field, oroutput_fieldif supplied
Has one optional argument:
- distinct¶
If
distinct=True,Avgreturns the mean value of unique values. This is the SQL equivalent ofAVG(DISTINCT <field>). The default value isFalse.
Changed in Django 3.0:Support for
distinct=Truewas added.
Count¶
- class Count(expression, distinct=False, filter=None, **extra)¶
Returns the number of objects that are related through the provided expression.
Псевдоним по-умолчанию:
<field>__countТип возвращаемого значения:
int
Has one optional argument:
- distinct¶
If
distinct=True, the count will only include unique instances. This is the SQL equivalent ofCOUNT(DISTINCT <field>). The default value isFalse.
Макс¶
- class Max(expression, output_field=None, filter=None, **extra)¶
Возвращает максимальное значение указанного выражения.
Псевдоним по-умолчанию:
<field>__maxReturn type: same as input field, or
output_fieldif supplied
Мин¶
- class Min(expression, output_field=None, filter=None, **extra)¶
Возвращает минимальное значение указанного выражения.
Псевдоним по-умолчанию:
<field>__minReturn type: same as input field, or
output_fieldif supplied
StdDev¶
- class StdDev(expression, output_field=None, sample=False, filter=None, **extra)¶
Возвращает стандартное отклонение для данных указанного выражения.
Псевдоним по-умолчанию:
<field>__stddevReturn type:
floatif input isint, otherwise same as input field, oroutput_fieldif supplied
Has one optional argument:
- sample¶
By default,
StdDevreturns the population standard deviation. However, ifsample=True, the return value will be the sample standard deviation.
Сумма¶
- class Sum(expression, output_field=None, distinct=False, filter=None, **extra)¶
Возвращает сумму всех значений указанного выражения.
Псевдоним по-умолчанию:
<field>__sumReturn type: same as input field, or
output_fieldif supplied
Has one optional argument:
- distinct¶
If
distinct=True,Sumreturns the sum of unique values. This is the SQL equivalent ofSUM(DISTINCT <field>). The default value isFalse.
Changed in Django 3.0:Support for
distinct=Truewas added.
Variance¶
- class Variance(expression, output_field=None, sample=False, filter=None, **extra)¶
Возвращает дисперсию значений в указанном выражении.
Псевдоним по-умолчанию:
<field>__varianceReturn type:
floatif input isint, otherwise same as input field, oroutput_fieldif supplied
Has one optional argument:
- sample¶
By default,
Variancereturns the population variance. However, ifsample=True, the return value will be the sample variance.