QuerySet API reference

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

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

When QuerySets are evaluated

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

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

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

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

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

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

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

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

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

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

    Заметка: Не используйте len() с QuerySet если вам нужно узнать только количество записей в выборке. Эффективнее использовать подсчет на уровне базы данных, используя оператор SQL SELECT 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().

Pickling QuerySets

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

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

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

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

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

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

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

QuerySet API

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

class QuerySet(model=None, query=None, using=None, hints=None)

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

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

ordered

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

db

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

Примечание

The query parameter to QuerySet exists so that specialized query subclasses can reconstruct internal query state. The value of the parameter is an opaque representation of that query state and is not part of a public API. To put it another way: if you need to ask, you don’t need to use it.

Methods that return new QuerySets

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

filter()

filter(**kwargs)

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

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

Если вам необходимо выполнить более сложные вопросы (например, запросы с OR), вы можете использовать объект Q.

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')

In SQL terms, that evaluates to:

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')

In SQL terms, that evaluates to:

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

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

Если вам необходимо выполнить более сложные вопросы (например, запросы с OR), вы можете использовать объект Q.

annotate()

annotate(*args, **kwargs)

Annotates each object in the QuerySet with the provided list of query expressions. An expression may be a simple value, a reference to a field on the model (or any related models), or an aggregate expression (averages, sums, etc.) that has been computed over the objects that are related to the objects in the QuerySet.

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

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

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

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

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

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

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

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

order_by()

order_by(*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')

You can also order by query expressions by calling asc() or desc() on the expression:

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

asc() and desc() have arguments (nulls_first and nulls_last) that control how null values are sorted.

Будьте осторожны используя по полю из связанной модели и метод 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')

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

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

If a query doesn’t have an ordering specified, results are returned from the database in an unspecified order. A particular ordering is guaranteed only when ordering by a set of fields that uniquely identify each object in the results. For example, if a name field isn’t unique, ordering by it won’t guarantee objects with the same name always appear in the same order.

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. Если вы не определите сортировку, будут возвращены случайные записи для каждого уникального значения.

Примеры (все, кроме первого, будут работать только в 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. Вам необходимо явно отсортировать по внешнему ключу (blog_id в этому случае), или полю связанной модели (blog__pk), чтобы поля совпадали.

values()

values(*fields, **expressions)

Возвращает QuerySet , который возвращает словари с результатом вместо объектов моделей.

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

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

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

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

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

Например:

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

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() не имеет смысла. В таком случае будет вызвано исключение NotImplementedError.

  • Combining transforms and aggregates requires the use of two annotate() calls, either explicitly or as keyword arguments to values(). As above, if the transform has been registered on the relevant field type the first annotate() 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()), хотя это и не имеет значения. Это ваш шанс проявить индивидуальность.

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

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

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

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

values_list()

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

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'), ...]>

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

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

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

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

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'), ...]>

Using a named tuple may make use of the results more readable, at the expense of a small performance penalty for transforming the results into a named tuple.

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

Распространенная задача получить значение поля из определенной записи. Для этого используйте values_list() и get():

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

values() and values_list() are both intended as optimizations for a specific use case: retrieving a subset of data without the overhead of creating a model instance. This metaphor falls apart when dealing with many-to-many and other multivalued relations (such as the one-to-many relation of a reverse foreign key) because the «one row, one object» assumption doesn’t hold.

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)]>

Authors with multiple entries appear multiple times and authors without any entries have None for the entry headline.

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,)]>

dates()

dates(field, kind, order='ASC')

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

field should be the name of a DateField of your model. kind should be either "year", "month", "week", or "day". Each datetime.date object in the result list is «truncated» to the given type.

  • "year" возвращает список уникальных значений года из всех дат указанного поля.
  • "month" возвращает список уникальных значений года/месяца из всех дат указанного поля.
  • "week" returns a list of all distinct year/week values for the field. All dates will be a Monday.
  • "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)

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

field_name – название поля модели типа DateTimeField.

kind should be either "year", "month", "week", "day", "hour", "minute", or "second". Each datetime.datetime object in the result list is «truncated» to the given type.

order – сортировка значений. По-умолчанию 'ASC', должна быть 'ASC' или 'DESC'.

tzinfo указывает часовой пояс используемый при создании объектов datetime. Принимает объект datetime.tzinfo. Если передать None, Django использует текущий часовой пояс. Не используется при USE_TZ равном False.

Примечание

Функция выполняет преобразование даты на уровне базы данных. Поэтому ваша база данных должна понимать значение вида 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: load the time zone tables with mysql_tzinfo_to_sql.

none()

none()

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

Например:

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

all()

all()

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

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

union()

union(*other_qs, all=False)

Uses SQL’s UNION operator to combine the results of two or more QuerySets. For example:

>>> qs1.union(qs2, qs3)

The UNION operator selects only distinct values by default. To allow duplicate values, use the all=True argument.

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 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.

intersection()

intersection(*other_qs)

Uses SQL’s INTERSECT operator to return the shared elements of two or more QuerySets. For example:

>>> qs1.intersection(qs2, qs3)

See union() for some restrictions.

difference()

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)

See union() for some restrictions.

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(). Мы больше не улучшаем и не исправляем ошибки для этого метода.

Например, это использование 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 используется как под-запрос в другом запросе).

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

You should be very careful whenever you use extra(). Every time you use it, you should escape any parameters that the user can control by using params in order to protect against SQL injection attacks.

You also must not quote placeholders in the SQL string. This example is vulnerable to SQL injection because of the quotes around %s:

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

You can read more about how Django’s SQL injection protection works.

По определению, дополнительные параметры поиска определенные в 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 inserts the given SQL snippet directly into the SELECT statement, so the resulting SQL of the above example would be something like:

    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.

    The resulting SQL of the above example would be:

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

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

    In some rare cases, you might wish to pass parameters to the SQL fragments in extra(select=...). For this purpose, use the select_params parameter.

    Например:

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

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

  • where / tables

    Вы можете добавить оператор SQL WHERE — возможно для выполнения не явного объединения таблиц — by using where. Используя параметр tables можно добавить таблицы в оператор SQL FROM.

    where и tables принимают список строк. Все параметры where будут добавлены к остальным критериям через оператор «AND» .

    Например:

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

    …translates (roughly) into the following 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()) предназначены только для опытных пользователей. Они предоставляют возможность оптимизировать запрос. Но для начала вам следует проанализировать его, точно определить какие данные вам необходимы и удостовериться, что разница между получением всех полей и получением определенных, будет значительной.

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

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

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

    class Meta:
        managed = False
        db_table = 'app_largetable'

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

    class Meta:
        db_table = 'app_largetable'

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

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

Примечание

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

only()

only(*fields)

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

Например, у вас есть модель с полями 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(). Используйте его с осторожностью и только в отсутствии других вариантов.

При использовании only() без полей, указанных в select_related(), будет вызвано исключение.

Примечание

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

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:
        ...

When the queryset is evaluated (for entry in entries in this case), all matched entries will be locked until the end of the transaction block, meaning that other transactions will be prevented from changing or acquiring locks on them.

Usually, if another transaction has already acquired a lock on one of the selected rows, the query will block until the lock is released. If this is not the behavior you want, call select_for_update(nowait=True). This will make the call non-blocking. If a conflicting lock is already acquired by another transaction, DatabaseError will be raised when the queryset is evaluated. You can also ignore locked rows by using select_for_update(skip_locked=True) instead. The nowait and skip_locked are mutually exclusive and attempts to call select_for_update() with both options enabled will result in a ValueError.

By default, select_for_update() locks all rows that are selected by the query. For example, rows of related objects specified in select_related() are locked in addition to rows of the queryset’s model. If this isn’t desired, specify the related objects you want to lock in select_for_update(of=(...)) using the same fields syntax as select_related(). Use the value 'self' to refer to the queryset’s model.

Lock parents models in select_for_update(of=(...))

If you want to lock parents models when using multi-table inheritance, you must specify parent link fields (by default <parent_model_name>_ptr) in the of argument. For example:

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.

Certain expressions may not be supported

PostgreSQL doesn’t support select_for_update() with Window expressions.

raw()

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

Takes a raw SQL query, executes it, and returns a django.db.models.query.RawQuerySet instance. This RawQuerySet instance can be iterated over just like a normal QuerySet to provide object instances.

Смотрите Использование чистого SQL.

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

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

Operators that return new QuerySets

Combined querysets must use the same model.

AND (&)

Combines two QuerySets using the SQL AND operator.

The following are equivalent:

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 equivalent:

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

OR (|)

Combines two QuerySets using the SQL OR operator.

The following are equivalent:

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 equivalent:

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

Methods that do not return QuerySets

Следующие методы выполняют QuerySet и возвращают не QuerySet.

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

get()

get(**kwargs)

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

get() вызывает исключение MultipleObjectsReturned, если найдено более одно объекта. MultipleObjectsReturned – атрибут класса модели.

get() вызывает исключение DoesNotExist, если ни один объект не был найден. Это исключение также атрибут класса модели. Например:

Entry.objects.get(id='foo') # raises Entry.DoesNotExist

Исключение DoesNotExist унаследовано от django.core.exceptions.ObjectDoesNotExist,таким образом можно обработать несколько исключений DoesNotExist. Например:

from django.core.exceptions import ObjectDoesNotExist
try:
    e = Entry.objects.get(id=3)
    b = Blog.objects.get(id=1)
except ObjectDoesNotExist:
    print("Either the entry or blog doesn't exist.")

If you expect a queryset to return one row, you can use get() without any arguments to return the object for that row:

entry = Entry.objects.filter(...).exclude(...).get()

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 – булево значение, указывающее был ли создан объект.

This is meant to prevent duplicate objects from being created when requests are made in parallel, and as a shortcut to boilerplatish code. For example:

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()

Here, with concurrent requests, multiple attempts to save a Person with the same parameters may be made. To avoid this race condition, the above example can be rewritten using get_or_create() like so:

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

Any keyword arguments passed to get_or_create()except an optional one called defaults — will be used in a get() call. If an object is found, get_or_create() returns a tuple of that object and False.

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

This method is atomic assuming that the database enforces uniqueness of the keyword arguments (see unique or unique_together). If the fields used in the keyword arguments do not have a uniqueness constraint, concurrent calls to this method may result in multiple rows with the same parameters being inserted.

You can specify more complex conditions for the retrieved object by chaining get_or_create() with filter() and using Q objects. For example, to retrieve Robert or Bob Marley if either exists, and create the latter otherwise:

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'})

If multiple objects are found, get_or_create() raises MultipleObjectsReturned. If an object is not found, get_or_create() will instantiate and save a new object, returning a tuple of the new object and True. The new object will be created roughly according to this algorithm:

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()

In English, that means start with any non-'defaults' keyword argument that doesn’t contain a double underscore (which would indicate a non-exact lookup). Then add the contents of defaults, overriding any keys if necessary, and use the result as the keyword arguments to the model class. If there are any callables in defaults, evaluate them. As hinted at above, this is a simplification of the algorithm that is used, but it contains all the pertinent details. The internal implementation has some more error-checking than this and handles some extra edge-conditions; if you’re interested, read the code.

If you have a field named defaults and want to use it as an exact lookup in get_or_create(), use 'defaults__exact', like so:

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)

Вы можете использовать get_or_create() для поля chapters модели 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'},
)

Подробности о том, как обрабатывается kwargs, смотрите в описании get_or_create().

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

Like get_or_create() and create(), if you’re using manually specified primary keys and an object needs to be created but the key already exists in the database, an IntegrityError is raised.

bulk_create()

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

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

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

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

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

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

  • If the model’s primary key is an AutoField it does not retrieve and set the primary key attribute, as save() does, unless the database backend supports it (currently PostgreSQL).

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

  • It casts objs to a list, which fully evaluates objs if it’s a generator. The cast allows inspecting all objects so that any objects with a manually set primary key can be inserted first. If you want to insert objects in batches without evaluating the entire generator at once, you can use this technique as long as the objects don’t have any manually set primary keys:

    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)
    

The batch_size parameter controls how many objects are created in a single query. The default is to create all objects in one batch, except for SQLite where the default is such that at most 999 variables per query are used.

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).

Changed in Django 2.2:

The ignore_conflicts parameter was added.

bulk_update()

New in Django 2.2.
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() is used to save the changes, so this is more efficient than iterating through the list of models and calling save() on each of them, but it has a few caveats:

  • You cannot update the model’s primary key.
  • Each model’s save() method isn’t called, and the pre_save and post_save signals aren’t sent.
  • If updating a large number of columns in a large number of rows, the SQL generated can be very large. Avoid this by specifying a suitable batch_size.
  • Updating fields defined on multi-table inheritance ancestors will incur an extra query per ancestor.
  • If objs contains duplicates, only the first one is updated.

The batch_size parameter controls how many objects are saved in a single query. The default is to update all objects in one batch, except for SQLite and Oracle which have restrictions on the number of variables used in a query.

count()

count()

Returns an integer representing the number of objects in the database matching the QuerySet.

Например:

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

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

Метод count() использует 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)

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

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

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

Depending on the database backend, query results will either be loaded all at once or streamed from the database using server-side cursors.

With server-side cursors

Oracle and PostgreSQL use server-side cursors to stream results from the database without loading the entire result set into memory.

The Oracle database driver always uses server-side cursors.

With server-side cursors, the chunk_size parameter specifies the number of results to cache at the database driver level. Fetching bigger chunks diminishes the number of round trips between the database driver and the database, at the expense of memory.

On PostgreSQL, server-side cursors will only be used when the DISABLE_SERVER_SIDE_CURSORS setting is False. Read Transaction pooling and server-side cursors if you’re using a connection pooler configured in transaction pooling mode. When server-side cursors are disabled, the behavior is the same as databases that don’t support server-side cursors.

Without server-side cursors

MySQL doesn’t support streaming results, hence the Python database driver loads the entire result set into memory. The result set is then transformed into Python row objects by the database adapter using the fetchmany() method defined in PEP 249.

SQLite can fetch results in batches using fetchmany(), but since SQLite doesn’t provide isolation between queries within a connection, be careful when writing to the table being iterated over. See Isolation when using QuerySet.iterator() for more information.

The chunk_size parameter controls the size of batches Django retrieves from the database driver. Larger batches decrease the overhead of communicating with the database driver at the expense of a slight increase in memory consumption.

The default value of chunk_size, 2000, comes from a calculation on the psycopg mailing list:

Assuming rows of 10-20 columns with a mix of textual and numeric data, 2000 is going to fetch less than 100KB of data, which seems a good compromise between the number of rows transferred and the data discarded if the loop is exited early.
Changed in Django 2.2:

Support for result streaming on SQLite was added.

latest()

latest(*fields)

Returns the latest object in the table based on the given field(s).

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

Entry.objects.latest('pub_date')

You can also choose the latest based on several fields. For example, to select the Entry with the earliest expire_date when two entries have the same pub_date:

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

The negative sign in '-expire_date' means to sort expire_date in descending order. Since latest() gets the last result, the Entry with the earliest expire_date is selected.

If your model’s Meta specifies get_latest_by, you can omit any arguments to earliest() or latest(). The fields specified in get_latest_by will be used by default.

Как и get(), earliest() и latest() вызывает исключение DoesNotExist, если объект не найден.

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

earliest() and latest() may return instances with null dates.

Since ordering is delegated to the database, results on fields that allow null values may be ordered differently if you use different databases. For example, PostgreSQL and MySQL sort null values as if they are higher than non-null values, while SQLite does the opposite.

You may want to filter out null values:

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

earliest()

earliest(*fields)

Работает как и latest() только наоборот.

first()

first()

Returns the first object matched by the queryset, or None if there is no matching object. If the QuerySet has no ordering defined, then the queryset is automatically ordered by the primary key. This can affect aggregation results as described in Влияние сортировки по-умолчанию и order_by().

Например:

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

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

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

last()

last()

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

aggregate()

aggregate(*args, **kwargs)

Returns a dictionary of aggregate values (averages, sums, etc.) calculated over the QuerySet. Each argument to aggregate() specifies a value that will be included in the dictionary that is returned.

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

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

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

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

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

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

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

exists()

exists()

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

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

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

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

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

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

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

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

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

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

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

Additionally, if a some_queryset has not yet been evaluated, but you know that it will be at some point, then using some_queryset.exists() will do more overall work (one query for the existence check plus an extra one to later retrieve the results) than using bool(some_queryset), which retrieves the results and then checks if any were returned.

update()

update(**kwargs)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

…делайте так:

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

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

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

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

delete()

delete()

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

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

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

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

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

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

>>> 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. Смотрите Creating a manager with QuerySet methods.

explain()

explain(format=None, **options)

Returns a string of the QuerySet’s execution plan, which details how the database would execute the query, including any indexes or joins that would be used. Knowing these details may help you improve the performance of slow queries.

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)

The output differs significantly between databases.

explain() is supported by all built-in database backends except Oracle because an implementation there isn’t straightforward.

The format parameter changes the output format from the databases’s default, usually text-based. PostgreSQL supports 'TEXT', 'JSON', 'YAML', and 'XML'. MySQL supports 'TEXT' (also called 'TRADITIONAL') and 'JSON'.

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))
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

On some databases, flags may cause the query to be executed which could have adverse effects on your database. For example, PostgreSQL’s ANALYZE flag could result in changes to data if there are triggers or if a function is called, even for a SELECT query.

Field lookups

Операторы фильтрации используются для создания оператора WHERE в SQL. Они используются как именованные аргументы для методов QuerySet: filter(), exclude() и get().

Введение смотрите в разделе о моделях и выполнении запросов к базе данных.

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

По умолчанию, если тип фильтра явно не указан (например, Entry.objects.get(id=14)), подразумевается exact.

exact

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

Например:

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

SQL equivalents:

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 equivalents:

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

Обратите внимание, будет найден 'Beatles Blog', 'beatles blog', 'BeAtLes BLoG' и тд.

Пользователям SQLite

When using the SQLite backend and non-ASCII strings, bear in mind the database note about string comparisons. SQLite does not do case-insensitive matching for non-ASCII strings.

contains

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

Например:

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

SQL equivalent:

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 equivalent:

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

Пользователям SQLite

When using the SQLite backend and non-ASCII strings, bear in mind the database note about string comparisons.

in

In a given iterable; often a list, tuple, or queryset. It’s not a common use case, but strings (being iterables) are accepted.

Например:

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

SQL equivalents:

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)

This queryset will be evaluated as subselect statement:

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 are lazy.

gt

Больше чем.

Например:

Entry.objects.filter(id__gt=4)

SQL equivalent:

SELECT ... WHERE id > 4;

gte

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

lt

Меньше чем.

lte

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

startswith

Регистрозависимая проверка начинается ли поле с указанного значения.

Например:

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

SQL equivalent:

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

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

istartswith

Регистронезависимая проверка начинается ли поле с указанного значения.

Например:

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

SQL equivalent:

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

Пользователям SQLite

When using the SQLite backend and non-ASCII strings, bear in mind the database note about string comparisons.

endswith

Регистрозависимая проверка оканчивается ли поле с указанного значения.

Например:

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

SQL equivalent:

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

Пользователям SQLite

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

iendswith

Регистронезависимая проверка оканчивается ли поле с указанного значения.

Например:

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

SQL equivalent:

SELECT ... WHERE headline ILIKE '%Lennon'

Пользователям SQLite

When using the SQLite backend and non-ASCII strings, bear in mind the database note about string comparisons.

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 equivalent:

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

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

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

Filtering a DateTimeField with dates won’t include items on the last day, because the bounds are interpreted as «0am on the given date». If pub_date was a DateTimeField, the above expression would be turned into this 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 не представлен т.к. реализация отличается для различных баз данных.)

When USE_TZ is True, fields are converted to the current time zone before filtering. This requires time zone definitions in the database.

year

Проверка года для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает числовое значение года.

Например:

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

SQL equivalent:

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

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

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

iso_year

New in Django 2.2.

For date and datetime fields, an exact ISO 8601 week-numbering year match. Allows chaining additional field lookups. Takes an integer year.

Например:

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 equivalent:

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

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

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

day

Проверка дня месяца для полей date/datetime. Позволяет использовать дополнительные проверки поля. Принимает номер дня месяца.

Например:

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

SQL equivalent:

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

For date and datetime fields, return the week number (1-52 or 53) according to ISO-8601, i.e., weeks start on a Monday and the first week contains the year’s first Thursday.

Например:

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 будет преобразовано в текущий часовой пояс. Для этого необходимо настроить часовые пояса для базы данных.

quarter

For date and datetime fields, a „quarter of the year“ match. Allows chaining additional field lookups. Takes an integer value between 1 and 4 representing the quarter of the year.

Example to retrieve entries in the second quarter (April 1 to June 30):

Entry.objects.filter(pub_date__quarter=2)

(Аналог SQL не представлен т.к. реализация отличается для различных баз данных.)

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

time

For datetime fields, casts the value as time. Allows chaining additional field lookups. Takes a datetime.time value.

Например:

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

(Аналог SQL не представлен т.к. реализация отличается для различных баз данных.)

When USE_TZ is True, fields are converted to the current time zone before filtering. This requires time zone definitions in the database.

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 equivalent:

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 equivalent:

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 equivalent:

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 equivalent:

SELECT ... WHERE pub_date IS NULL;

regex

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

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

Например:

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

SQL equivalents:

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 equivalents:

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 не умеет использовать агрегацию для полей даты и времени. Это потому что там нет встроенных полей даты и времени и Django эмулирует их используя текстовое поле. При использовании такой агрегации с SQLite вызовет NotImplementedError.

Внимание

Функция агрегации вернет None, если используется для пустого QuerySet. Например, Sum вернет None вместо 0, если QuerySet не содержит записей. Исключением является Count, который вернет 0 для пустого QuerySet.

Функции агрегации обычно принимают следующие параметры:

expressions

Strings that reference fields on the model, or query expressions.

output_field

Необязательный аргумент, который определяет поле модели результата.

Примечание

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

filter

An optional Q object that’s used to filter the rows that are aggregated.

See Conditional aggregation and Фильтрация по «аннотации» for example usage.

**extra

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

Avg

class Avg(expression, output_field=None, distinct=False, filter=None, **extra)

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

  • Псевдоним по-умолчанию: <field>__avg
  • Return type: float if input is int, otherwise same as input field, or output_field if supplied

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

distinct

If distinct=True, Avg returns the mean value of unique values. This is the SQL equivalent of AVG(DISTINCT <field>). The default value is False.

Changed in Django 3.0:

Support for distinct=True was added.

Count

class Count(expression, distinct=False, filter=None, **extra)

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

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

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

distinct

При distinct=True, будут подсчитаны только уникальные объекты. SQL эквивалент – COUNT(DISTINCT <field>). Значение по-умолчанию False.

Max

class Max(expression, output_field=None, filter=None, **extra)

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

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

Min

class Min(expression, output_field=None, filter=None, **extra)

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

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

StdDev

class StdDev(expression, output_field=None, sample=False, filter=None, **extra)

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

  • Псевдоним по-умолчанию: <field>__stddev
  • Return type: float if input is int, otherwise same as input field, or output_field if supplied

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

sample

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

Changed in Django 2.2:

SQLite support was added.

Sum

class Sum(expression, output_field=None, distinct=False, filter=None, **extra)

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

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

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

distinct

If distinct=True, Sum returns the sum of unique values. This is the SQL equivalent of SUM(DISTINCT <field>). The default value is False.

Changed in Django 3.0:

Support for distinct=True was added.

Variance

class Variance(expression, output_field=None, sample=False, filter=None, **extra)

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

  • Псевдоним по-умолчанию: <field>__variance
  • Return type: float if input is int, otherwise same as input field, or output_field if supplied

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

sample

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

Changed in Django 2.2:

SQLite support was added.