Spec-Zone.ru › Django 6.0

Функции базы данных

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

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

class Author(models.Model):
    name = models.CharField(max_length=50)
    age = models.PositiveIntegerField(null=True, blank=True)
    alias = models.CharField(max_length=50, null=True, blank=True)
    goes_by = models.CharField(max_length=50, null=True, blank=True)

Обычно мы не рекомендуем разрешать null=True для CharField, поскольку это позволяет полю иметь два «пустых значения», но это важно для приведенного ниже примера с Coalesce.

Функции сравнения и преобразования

Cast

class Cast(expression, output_field) [исходный код]

Принудительно задает для результата expression тип, указанный в output_field.

Пример использования:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Cast
>>> Author.objects.create(age=25, name="Margaret Smith")
>>> author = Author.objects.annotate(
...     age_as_float=Cast("age", output_field=FloatField()),
... ).get()
>>> print(author.age_as_float)
25.0

Coalesce

class Coalesce(*expressions, **extra) [исходный код]

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

Примеры использования:

>>> # Get a screen name from least to most public
>>> from django.db.models import Sum
>>> from django.db.models.functions import Coalesce
>>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
>>> author = Author.objects.annotate(screen_name=Coalesce("alias", "goes_by", "name")).get()
>>> print(author.screen_name)
Maggie

>>> # Prevent an aggregate Sum() from returning None
>>> # The aggregate default argument uses Coalesce() under the hood.
>>> aggregated = Author.objects.aggregate(
...     combined_age=Sum("age"),
...     combined_age_default=Sum("age", default=0),
...     combined_age_coalesce=Coalesce(Sum("age"), 0),
... )
>>> print(aggregated["combined_age"])
None
>>> print(aggregated["combined_age_default"])
0
>>> print(aggregated["combined_age_coalesce"])
0

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

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

>>> from django.db.models import DateTimeField
>>> from django.db.models.functions import Cast, Coalesce
>>> from django.utils import timezone
>>> now = timezone.now()
>>> Coalesce("updated", Cast(now, DateTimeField()))

Collate

class Collate(expression, collation) [исходный код]

Принимает выражение и имя параметров сортировки для использования в запросе.

Например, для фильтрации без учета регистра в SQLite:

>>> Author.objects.filter(name=Collate(Value("john"), "nocase"))
<QuerySet [<Author: John>, <Author: john>]>

Функцию также можно использовать при сортировке, например в PostgreSQL:

>>> Author.objects.order_by(Collate("name", "et-x-icu"))
<QuerySet [<Author: Ursula>, <Author: Veronika>, <Author: Ülle>]>

Greatest

class Greatest(*expressions, **extra) [исходный код]

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

Пример использования:

class Blog(models.Model):
    body = models.TextField()
    modified = models.DateTimeField(auto_now=True)


class Comment(models.Model):
    body = models.TextField()
    modified = models.DateTimeField(auto_now=True)
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
>>> from django.db.models.functions import Greatest
>>> blog = Blog.objects.create(body="Greatest is the best.")
>>> comment = Comment.objects.create(body="No, Least is better.", blog=blog)
>>> comments = Comment.objects.annotate(last_updated=Greatest("modified", "blog__modified"))
>>> annotated_comment = comments.get()

annotated_comment.last_updated будет самой поздней датой из blog.modified и comment.modified.

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

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

  • PostgreSQL: Greatest возвращает наибольшее ненулевое выражение или null, если все выражения равны null.
  • SQLite, Oracle и MySQL: если любое выражение равно null, Greatest возвращает null.

Поведение PostgreSQL можно имитировать с помощью Coalesce, если вы знаете разумное минимальное значение, которое можно указать по умолчанию.

Least

class Least(*expressions, **extra) [исходный код]

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

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

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

  • PostgreSQL: Least возвращает наименьшее ненулевое выражение или null, если все выражения равны null.
  • SQLite, Oracle и MySQL: если любое выражение равно null, Least возвращает null.

Поведение PostgreSQL можно имитировать с помощью Coalesce, если вы знаете разумное максимальное значение, которое можно указать по умолчанию.

NullIf

class NullIf(expression1, expression2) [исходный код]

Принимает два выражения и возвращает None, если они равны, в противном случае возвращает expression1.

Особенности Oracle

В соответствии с соглашением Oracle, эта функция возвращает пустую строку вместо None, если выражения имеют тип CharField.

Передавать Value(None) в expression1 в Oracle запрещено, поскольку Oracle не принимает NULL в качестве первого аргумента.

Функции для работы с датами

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

class Experiment(models.Model):
    start_datetime = models.DateTimeField()
    start_date = models.DateField(null=True, blank=True)
    start_time = models.TimeField(null=True, blank=True)
    end_datetime = models.DateTimeField(null=True, blank=True)
    end_date = models.DateField(null=True, blank=True)
    end_time = models.TimeField(null=True, blank=True)

Extract

class Extract(expression, lookup_name=None, tzinfo=None, **extra) [исходный код]

Извлекает компонент даты в виде числа.

Принимает expression, представляющий DateField, DateTimeField, TimeField или DurationField, и lookup_name, а возвращает часть даты, на которую ссылается lookup_name, в виде IntegerField. Django обычно использует функцию извлечения из базы данных, поэтому можно использовать любое lookup_name, поддерживаемое вашей базой данных. Для извлечения значения в определённом часовом поясе можно передать подкласс tzinfo, обычно предоставляемый модулем zoneinfo.

Для даты и времени 2015-06-15 23:30:01.000321+00:00 встроенные lookup_name возвращают:

  • “year”: 2015
  • “iso_year”: 2015
  • “quarter”: 2
  • “month”: 6
  • “day”: 15
  • “week”: 25
  • “week_day”: 2
  • “iso_week_day”: 1
  • “hour”: 23
  • “minute”: 30
  • “second”: 1

Если в Django активен другой часовой пояс, например Australia/Melbourne, дата и время перед извлечением значения преобразуются в этот часовой пояс. Смещение часового пояса для Мельбурна на указанную выше дату составляет +10:00. При активном часовом поясе будут возвращены те же значения, что и выше, за исключением следующих:

  • “day”: 16
  • “week_day”: 3
  • “iso_week_day”: 2
  • “hour”: 9

Значения week_day

week_day lookup_type вычисляется иначе, чем в большинстве баз данных и стандартных функциях Python. Эта функция возвращает 1 для воскресенья, 2 для понедельника и так далее до 7 для субботы.

Эквивалентное вычисление в Python:

>>> from datetime import datetime
>>> dt = datetime(2015, 6, 15)
>>> (dt.isoweekday() % 7) + 1
2

Значения week

week lookup_type вычисляется на основе ISO-8601, то есть неделя начинается в понедельник. Первая неделя года — это неделя, на которую приходится первый четверг года; иными словами, большая часть дней первой недели (четыре или более) должна приходиться на этот год. Возвращаемое значение находится в диапазоне от 1 до 52 или 53.

Каждому lookup_name выше соответствует подкласс Extract (перечисленные ниже), который обычно следует использовать вместо более многословного эквивалента; например, используйте ExtractYear(...) вместо Extract(..., lookup_name='year').

Пример использования:

>>> from datetime import datetime
>>> from django.db.models.functions import Extract
>>> start = datetime(2015, 6, 15)
>>> end = datetime(2015, 7, 2)
>>> Experiment.objects.create(
...     start_datetime=start, start_date=start.date(), end_datetime=end, end_date=end.date()
... )
>>> # Add the experiment start year as a field in the QuerySet.
>>> experiment = Experiment.objects.annotate(
...     start_year=Extract("start_datetime", "year")
... ).get()
>>> experiment.start_year
2015
>>> # How many experiments completed in the same year in which they started?
>>> Experiment.objects.filter(start_datetime__year=Extract("end_datetime", "year")).count()
1

Извлечения из DateField

class ExtractYear(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'year'
class ExtractIsoYear(expression, tzinfo=None, **extra) [исходный код]

Возвращает год в нумерации недель ISO-8601.

lookup_name = 'iso_year'
class ExtractMonth(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'month'
class ExtractDay(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'day'
class ExtractWeekDay(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'week_day'
class ExtractIsoWeekDay(expression, tzinfo=None, **extra) [исходный код]

Возвращает день недели ISO-8601, где день 1 — понедельник, а день 7 — воскресенье.

lookup_name = 'iso_week_day'
class ExtractWeek(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'week'
class ExtractQuarter(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'quarter'

Логически они эквивалентны Extract('date_field', lookup_name). Каждый класс также является Transform, зарегистрированным для DateField и DateTimeField как __(lookup_name), например __year.

Поскольку у DateFields нет компонента времени, с DateField можно использовать только подклассы Extract, работающие с частями даты:

>>> from datetime import UTC, datetime
>>> from django.db.models.functions import (
...     ExtractDay,
...     ExtractMonth,
...     ExtractQuarter,
...     ExtractWeek,
...     ExtractIsoWeekDay,
...     ExtractWeekDay,
...     ExtractIsoYear,
...     ExtractYear,
... )
>>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=UTC)
>>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=UTC)
>>> Experiment.objects.create(
...     start_datetime=start_2015,
...     start_date=start_2015.date(),
...     end_datetime=end_2015,
...     end_date=end_2015.date(),
... )
>>> Experiment.objects.annotate(
...     year=ExtractYear("start_date"),
...     isoyear=ExtractIsoYear("start_date"),
...     quarter=ExtractQuarter("start_date"),
...     month=ExtractMonth("start_date"),
...     week=ExtractWeek("start_date"),
...     day=ExtractDay("start_date"),
...     weekday=ExtractWeekDay("start_date"),
...     isoweekday=ExtractIsoWeekDay("start_date"),
... ).values(
...     "year",
...     "isoyear",
...     "quarter",
...     "month",
...     "week",
...     "day",
...     "weekday",
...     "isoweekday",
... ).get(
...     end_date__year=ExtractYear("start_date")
... )
{'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
 'day': 15, 'weekday': 2, 'isoweekday': 1}

Извлечения из DateTimeField

Помимо перечисленных ниже, для DateTimeFields также можно использовать все перечисленные выше извлечения для DateField.

class ExtractHour(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'hour'
class ExtractMinute(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'minute'
class ExtractSecond(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'second'

Логически они эквивалентны Extract('datetime_field', lookup_name). Каждый класс также является Transform, зарегистрированным для DateTimeField как __(lookup_name), например __minute.

Примеры с DateTimeField:

>>> from datetime import UTC, datetime
>>> from django.db.models.functions import (
...     ExtractDay,
...     ExtractHour,
...     ExtractMinute,
...     ExtractMonth,
...     ExtractQuarter,
...     ExtractSecond,
...     ExtractWeek,
...     ExtractIsoWeekDay,
...     ExtractWeekDay,
...     ExtractIsoYear,
...     ExtractYear,
... )
>>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=UTC)
>>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=UTC)
>>> Experiment.objects.create(
...     start_datetime=start_2015,
...     start_date=start_2015.date(),
...     end_datetime=end_2015,
...     end_date=end_2015.date(),
... )
>>> Experiment.objects.annotate(
...     year=ExtractYear("start_datetime"),
...     isoyear=ExtractIsoYear("start_datetime"),
...     quarter=ExtractQuarter("start_datetime"),
...     month=ExtractMonth("start_datetime"),
...     week=ExtractWeek("start_datetime"),
...     day=ExtractDay("start_datetime"),
...     weekday=ExtractWeekDay("start_datetime"),
...     isoweekday=ExtractIsoWeekDay("start_datetime"),
...     hour=ExtractHour("start_datetime"),
...     minute=ExtractMinute("start_datetime"),
...     second=ExtractSecond("start_datetime"),
... ).values(
...     "year",
...     "isoyear",
...     "month",
...     "week",
...     "day",
...     "weekday",
...     "isoweekday",
...     "hour",
...     "minute",
...     "second",
... ).get(
...     end_datetime__year=ExtractYear("start_datetime")
... )
{'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
 'day': 15, 'weekday': 2, 'isoweekday': 1, 'hour': 23, 'minute': 30,
 'second': 1}

Если USE_TZ имеет значение True, даты и время хранятся в базе данных в формате UTC. Если в Django активен другой часовой пояс, дата и время перед извлечением значения преобразуются в этот часовой пояс. Пример ниже выполняет преобразование в часовой пояс Мельбурна (UTC +10:00), что изменяет возвращаемые значения дня, дня недели и часа:

>>> from django.utils import timezone
>>> import zoneinfo
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")  # UTC+10:00
>>> with timezone.override(melb):
...     Experiment.objects.annotate(
...         day=ExtractDay("start_datetime"),
...         weekday=ExtractWeekDay("start_datetime"),
...         isoweekday=ExtractIsoWeekDay("start_datetime"),
...         hour=ExtractHour("start_datetime"),
...     ).values("day", "weekday", "isoweekday", "hour").get(
...         end_datetime__year=ExtractYear("start_datetime"),
...     )
...
{'day': 16, 'weekday': 3, 'isoweekday': 2, 'hour': 9}

Явная передача часового пояса функции Extract работает так же и имеет приоритет над активным часовым поясом:

>>> import zoneinfo
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
>>> Experiment.objects.annotate(
...     day=ExtractDay("start_datetime", tzinfo=melb),
...     weekday=ExtractWeekDay("start_datetime", tzinfo=melb),
...     isoweekday=ExtractIsoWeekDay("start_datetime", tzinfo=melb),
...     hour=ExtractHour("start_datetime", tzinfo=melb),
... ).values("day", "weekday", "isoweekday", "hour").get(
...     end_datetime__year=ExtractYear("start_datetime"),
... )
{'day': 16, 'weekday': 3, 'isoweekday': 2, 'hour': 9}

Now

class Now [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Now
>>> Article.objects.filter(published__lte=Now())
<QuerySet [<Article: How to Django>]>

Особенности PostgreSQL

В PostgreSQL SQL CURRENT_TIMESTAMP возвращает время начала текущей транзакции. Поэтому для совместимости с разными базами данных Now() использует вместо этого STATEMENT_TIMESTAMP. Если вам нужна временная метка транзакции, используйте django.contrib.postgres.functions.TransactionNow.

Oracle

В Oracle используется SQL LOCALTIMESTAMP, чтобы избежать проблем при приведении CURRENT_TIMESTAMP к DateTimeField.

Trunc

class Trunc(expression, kind, output_field=None, tzinfo=None, **extra) [исходный код]

Усекает дату до значимого компонента.

Если важно знать, произошло ли что-либо в определённом году, часу или дне, но не в конкретную секунду, Trunc (и его подклассы) может пригодиться для фильтрации или агрегации данных. Например, с помощью Trunc можно вычислить количество продаж за день.

Trunc принимает один expression, представляющий DateField, TimeField или DateTimeField, kind, представляющий часть даты или времени, и output_field, которое может быть DateTimeField(), TimeField() или DateField(). В зависимости от output_field функция возвращает дату и время, дату или время; поля вплоть до kind устанавливаются в минимальные значения. Если output_field не задано, по умолчанию используется output_field из expression. Для усечения значения в определённом часовом поясе можно передать подкласс tzinfo, обычно предоставляемый модулем zoneinfo.

Для даты и времени 2015-06-15 14:30:50.000321+00:00 встроенные kind возвращают:

  • “year”: 2015-01-01 00:00:00+00:00
  • “quarter”: 2015-04-01 00:00:00+00:00
  • “month”: 2015-06-01 00:00:00+00:00
  • “week”: 2015-06-15 00:00:00+00:00
  • “day”: 2015-06-15 00:00:00+00:00
  • “hour”: 2015-06-15 14:00:00+00:00
  • “minute”: 2015-06-15 14:30:00+00:00
  • “second”: 2015-06-15 14:30:50+00:00

Если в Django активен другой часовой пояс, например Australia/Melbourne, дата и время перед усечением значения преобразуются в новый часовой пояс. Смещение часового пояса для Мельбурна на указанную выше дату составляет +10:00. При активном часовом поясе будут возвращены следующие значения:

  • “year”: 2015-01-01 00:00:00+11:00
  • “quarter”: 2015-04-01 00:00:00+10:00
  • “month”: 2015-06-01 00:00:00+10:00
  • “week”: 2015-06-16 00:00:00+10:00
  • “day”: 2015-06-16 00:00:00+10:00
  • “hour”: 2015-06-16 00:00:00+10:00
  • “minute”: 2015-06-16 00:30:00+10:00
  • “second”: 2015-06-16 00:30:50+10:00

Для года смещение составляет +11:00, так как результат попадает на период летнего времени.

Каждому kind выше соответствует подкласс Trunc (перечисленные ниже), который обычно следует использовать вместо более многословного эквивалента; например, используйте TruncYear(...) вместо Trunc(..., kind='year').

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

Пример использования:

>>> from datetime import datetime
>>> from django.db.models import Count, DateTimeField
>>> from django.db.models.functions import Trunc
>>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 30, 50, 321))
>>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 40, 2, 123))
>>> Experiment.objects.create(start_datetime=datetime(2015, 12, 25, 10, 5, 27, 999))
>>> experiments_per_day = (
...     Experiment.objects.annotate(
...         start_day=Trunc("start_datetime", "day", output_field=DateTimeField())
...     )
...     .values("start_day")
...     .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_day:
...     print(exp["start_day"], exp["experiments"])
...
2015-06-15 00:00:00 2
2015-12-25 00:00:00 1
>>> experiments = Experiment.objects.annotate(
...     start_day=Trunc("start_datetime", "day", output_field=DateTimeField())
... ).filter(start_day=datetime(2015, 6, 15))
>>> for exp in experiments:
...     print(exp.start_datetime)
...
2015-06-15 14:30:50.000321
2015-06-15 14:40:02.000123

Усечение DateField

class TruncYear(expression, output_field=None, tzinfo=None, **extra) [исходный код]
kind = 'year'
class TruncMonth(expression, output_field=None, tzinfo=None, **extra) [исходный код]
kind = 'month'
class TruncWeek(expression, output_field=None, tzinfo=None, **extra) [исходный код]

Усекает дату до полуночи понедельника соответствующей недели.

kind = 'week'
class TruncQuarter(expression, output_field=None, tzinfo=None, **extra) [исходный код]
kind = 'quarter'

Логически они эквивалентны Trunc('date_field', kind). Они усекают все части даты вплоть до kind, что позволяет группировать или фильтровать даты с меньшей точностью. expression может иметь output_field типа DateField или DateTimeField.

Поскольку у DateFields нет компонента времени, с DateField можно использовать только подклассы Trunc, работающие с частями даты:

>>> from datetime import UTC, datetime
>>> from django.db.models import Count
>>> from django.db.models.functions import TruncMonth, TruncYear
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=UTC)
>>> start2 = datetime(2015, 6, 15, 14, 40, 2, 123, tzinfo=UTC)
>>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=UTC)
>>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
>>> Experiment.objects.create(start_datetime=start2, start_date=start2.date())
>>> Experiment.objects.create(start_datetime=start3, start_date=start3.date())
>>> experiments_per_year = (
...     Experiment.objects.annotate(year=TruncYear("start_date"))
...     .values("year")
...     .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_year:
...     print(exp["year"], exp["experiments"])
...
2014-01-01 1
2015-01-01 2

>>> import zoneinfo
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
>>> experiments_per_month = (
...     Experiment.objects.annotate(month=TruncMonth("start_datetime", tzinfo=melb))
...     .values("month")
...     .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_month:
...     print(exp["month"], exp["experiments"])
...
2015-06-01 00:00:00+10:00 1
2016-01-01 00:00:00+11:00 1
2014-06-01 00:00:00+10:00 1

Усечение DateTimeField

class TruncDate(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'date'
output_field = DateField()

TruncDate приводит expression к типу даты, а не использует встроенную функцию усечения SQL. Он также зарегистрирован как преобразование для DateTimeField под именем __date.

class TruncTime(expression, tzinfo=None, **extra) [исходный код]
lookup_name = 'time'
output_field = TimeField()

TruncTime приводит expression к типу времени, а не использует встроенную функцию усечения SQL. Он также зарегистрирован как преобразование для DateTimeField под именем __time.

class TruncDay(expression, output_field=None, tzinfo=None, **extra) [исходный код]
kind = 'day'
class TruncHour(expression, output_field=None, tzinfo=None, **extra) [исходный код]
kind = 'hour'
class TruncMinute(expression, output_field=None, tzinfo=None, **extra) [исходный код]
kind = 'minute'
class TruncSecond(expression, output_field=None, tzinfo=None, **extra) [исходный код]
kind = 'second'

Логически они эквивалентны Trunc('datetime_field', kind). Они усекают все части даты вплоть до kind и позволяют группировать или фильтровать даты и время с меньшей точностью. expression должен иметь output_field типа DateTimeField.

Пример использования:

>>> from datetime import UTC, date, datetime
>>> from django.db.models import Count
>>> from django.db.models.functions import (
...     TruncDate,
...     TruncDay,
...     TruncHour,
...     TruncMinute,
...     TruncSecond,
... )
>>> import zoneinfo
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=UTC)
>>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
>>> Experiment.objects.annotate(
...     date=TruncDate("start_datetime"),
...     day=TruncDay("start_datetime", tzinfo=melb),
...     hour=TruncHour("start_datetime", tzinfo=melb),
...     minute=TruncMinute("start_datetime"),
...     second=TruncSecond("start_datetime"),
... ).values("date", "day", "hour", "minute", "second").get()
{'date': datetime.date(2014, 6, 15),
 'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
 'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
 'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=UTC),
 'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=UTC)
}

Усечение TimeField

classTruncHour(expression, output_field=None, tzinfo=None, **extra)[исходный код]
kind = 'hour'
classTruncMinute(expression, output_field=None, tzinfo=None, **extra)[исходный код]
kind = 'minute'
classTruncSecond(expression, output_field=None, tzinfo=None, **extra)[исходный код]
kind = 'second'

Логически они эквивалентны Trunc('time_field', kind). Они усекают все части времени вплоть до kind, что позволяет группировать или фильтровать время с меньшей точностью. expression может иметь output_field типа TimeField или DateTimeField.

Поскольку у TimeFields нет компонента даты, с TimeField можно использовать только подклассы Trunc, работающие с частями времени:

>>> from datetime import UTC, datetime
>>> from django.db.models import Count, TimeField
>>> from django.db.models.functions import TruncHour
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=UTC)
>>> start2 = datetime(2014, 6, 15, 14, 40, 2, 123, tzinfo=UTC)
>>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=UTC)
>>> Experiment.objects.create(start_datetime=start1, start_time=start1.time())
>>> Experiment.objects.create(start_datetime=start2, start_time=start2.time())
>>> Experiment.objects.create(start_datetime=start3, start_time=start3.time())
>>> experiments_per_hour = (
...     Experiment.objects.annotate(
...         hour=TruncHour("start_datetime", output_field=TimeField()),
...     )
...     .values("hour")
...     .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_hour:
...     print(exp["hour"], exp["experiments"])
...
14:00:00 2
17:00:00 1

>>> import zoneinfo
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
>>> experiments_per_hour = (
...     Experiment.objects.annotate(
...         hour=TruncHour("start_datetime", tzinfo=melb),
...     )
...     .values("hour")
...     .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_hour:
...     print(exp["hour"], exp["experiments"])
...
2014-06-16 00:00:00+10:00 2
2016-01-01 04:00:00+11:00 1

Функции JSON

JSONArray

Добавлено в Django 5.2.
class JSONArray(*expressions) [исходный код]

Принимает список имён полей или выражений и возвращает массив JSON, содержащий эти значения.

Пример использования:

>>> from django.db.models import F
>>> from django.db.models.functions import JSONArray, Lower
>>> Author.objects.create(name="Margaret Smith", alias="msmith", age=25)
>>> author = Author.objects.annotate(
...     json_array=JSONArray(
...         Lower("name"),
...         "alias",
...         F("age") * 2,
...     )
... ).get()
>>> author.json_array
['margaret smith', 'msmith', 50]

JSONObject

class JSONObject(**fields) [исходный код]

Принимает список пар «ключ-значение» и возвращает объект JSON, содержащий эти пары.

Пример использования:

>>> from django.db.models import F
>>> from django.db.models.functions import JSONObject, Lower
>>> Author.objects.create(name="Margaret Smith", alias="msmith", age=25)
>>> author = Author.objects.annotate(
...     json_object=JSONObject(
...         name=Lower("name"),
...         alias="alias",
...         age=F("age") * 2,
...     )
... ).get()
>>> author.json_object
{'name': 'margaret smith', 'alias': 'msmith', 'age': 50}

Математические функции

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

class Vector(models.Model):
    x = models.FloatField()
    y = models.FloatField()

Abs

class Abs(expression, **extra) [исходный код]

Возвращает абсолютное значение числового поля или выражения.

Пример использования:

>>> from django.db.models.functions import Abs
>>> Vector.objects.create(x=-0.5, y=1.1)
>>> vector = Vector.objects.annotate(x_abs=Abs("x"), y_abs=Abs("y")).get()
>>> vector.x_abs, vector.y_abs
(0.5, 1.1)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Abs
>>> FloatField.register_lookup(Abs)
>>> # Get vectors inside the unit cube
>>> vectors = Vector.objects.filter(x__abs__lt=1, y__abs__lt=1)

ACos

class ACos(expression, **extra) [исходный код]

Возвращает арккосинус числового поля или выражения. Значение выражения должно находиться в диапазоне от -1 до 1.

Пример использования:

>>> from django.db.models.functions import ACos
>>> Vector.objects.create(x=0.5, y=-0.9)
>>> vector = Vector.objects.annotate(x_acos=ACos("x"), y_acos=ACos("y")).get()
>>> vector.x_acos, vector.y_acos
(1.0471975511965979, 2.6905658417935308)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import ACos
>>> FloatField.register_lookup(ACos)
>>> # Get vectors whose arccosine is less than 1
>>> vectors = Vector.objects.filter(x__acos__lt=1, y__acos__lt=1)

ASin

class ASin(expression, **extra) [исходный код]

Возвращает арксинус числового поля или выражения. Значение выражения должно находиться в диапазоне от -1 до 1.

Пример использования:

>>> from django.db.models.functions import ASin
>>> Vector.objects.create(x=0, y=1)
>>> vector = Vector.objects.annotate(x_asin=ASin("x"), y_asin=ASin("y")).get()
>>> vector.x_asin, vector.y_asin
(0.0, 1.5707963267948966)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import ASin
>>> FloatField.register_lookup(ASin)
>>> # Get vectors whose arcsine is less than 1
>>> vectors = Vector.objects.filter(x__asin__lt=1, y__asin__lt=1)

ATan

class ATan(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import ATan
>>> Vector.objects.create(x=3.12, y=6.987)
>>> vector = Vector.objects.annotate(x_atan=ATan("x"), y_atan=ATan("y")).get()
>>> vector.x_atan, vector.y_atan
(1.2606282660069106, 1.428638798133829)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import ATan
>>> FloatField.register_lookup(ATan)
>>> # Get vectors whose arctangent is less than 2
>>> vectors = Vector.objects.filter(x__atan__lt=2, y__atan__lt=2)

ATan2

class ATan2(expression1, expression2, **extra) [исходный код]

Возвращает арктангенс expression1 / expression2.

Пример использования:

>>> from django.db.models.functions import ATan2
>>> Vector.objects.create(x=2.5, y=1.9)
>>> vector = Vector.objects.annotate(atan2=ATan2("x", "y")).get()
>>> vector.atan2
0.9209258773829491

Ceil

class Ceil(expression, **extra) [исходный код]

Возвращает наименьшее целое число, большее или равное числовому полю или выражению.

Пример использования:

>>> from django.db.models.functions import Ceil
>>> Vector.objects.create(x=3.12, y=7.0)
>>> vector = Vector.objects.annotate(x_ceil=Ceil("x"), y_ceil=Ceil("y")).get()
>>> vector.x_ceil, vector.y_ceil
(4.0, 7.0)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Ceil
>>> FloatField.register_lookup(Ceil)
>>> # Get vectors whose ceil is less than 10
>>> vectors = Vector.objects.filter(x__ceil__lt=10, y__ceil__lt=10)

Cos

class Cos(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Cos
>>> Vector.objects.create(x=-8.0, y=3.1415926)
>>> vector = Vector.objects.annotate(x_cos=Cos("x"), y_cos=Cos("y")).get()
>>> vector.x_cos, vector.y_cos
(-0.14550003380861354, -0.9999999999999986)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Cos
>>> FloatField.register_lookup(Cos)
>>> # Get vectors whose cosine is less than 0.5
>>> vectors = Vector.objects.filter(x__cos__lt=0.5, y__cos__lt=0.5)

Cot

class Cot(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Cot
>>> Vector.objects.create(x=12.0, y=1.0)
>>> vector = Vector.objects.annotate(x_cot=Cot("x"), y_cot=Cot("y")).get()
>>> vector.x_cot, vector.y_cot
(-1.5726734063976826, 0.642092615934331)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Cot
>>> FloatField.register_lookup(Cot)
>>> # Get vectors whose cotangent is less than 1
>>> vectors = Vector.objects.filter(x__cot__lt=1, y__cot__lt=1)

Degrees

class Degrees(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Degrees
>>> Vector.objects.create(x=-1.57, y=3.14)
>>> vector = Vector.objects.annotate(x_d=Degrees("x"), y_d=Degrees("y")).get()
>>> vector.x_d, vector.y_d
(-89.95437383553924, 179.9087476710785)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Degrees
>>> FloatField.register_lookup(Degrees)
>>> # Get vectors whose degrees are less than 360
>>> vectors = Vector.objects.filter(x__degrees__lt=360, y__degrees__lt=360)

Exp

class Exp(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Exp
>>> Vector.objects.create(x=5.4, y=-2.0)
>>> vector = Vector.objects.annotate(x_exp=Exp("x"), y_exp=Exp("y")).get()
>>> vector.x_exp, vector.y_exp
(221.40641620418717, 0.1353352832366127)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Exp
>>> FloatField.register_lookup(Exp)
>>> # Get vectors whose exp() is greater than 10
>>> vectors = Vector.objects.filter(x__exp__gt=10, y__exp__gt=10)

Floor

class Floor(expression, **extra) [исходный код]

Возвращает наибольшее целое число, не превышающее числовое поле или выражение.

Пример использования:

>>> from django.db.models.functions import Floor
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_floor=Floor("x"), y_floor=Floor("y")).get()
>>> vector.x_floor, vector.y_floor
(5.0, -3.0)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Floor
>>> FloatField.register_lookup(Floor)
>>> # Get vectors whose floor() is greater than 10
>>> vectors = Vector.objects.filter(x__floor__gt=10, y__floor__gt=10)

Ln

class Ln(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Ln
>>> Vector.objects.create(x=5.4, y=233.0)
>>> vector = Vector.objects.annotate(x_ln=Ln("x"), y_ln=Ln("y")).get()
>>> vector.x_ln, vector.y_ln
(1.6863989535702288, 5.4510384535657)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Ln
>>> FloatField.register_lookup(Ln)
>>> # Get vectors whose value greater than e
>>> vectors = Vector.objects.filter(x__ln__gt=1, y__ln__gt=1)

Log

class Log(expression1, expression2, **extra) [исходный код]

Принимает два числовых поля или выражения и возвращает логарифм второго по основанию первого.

Пример использования:

>>> from django.db.models.functions import Log
>>> Vector.objects.create(x=2.0, y=4.0)
>>> vector = Vector.objects.annotate(log=Log("x", "y")).get()
>>> vector.log
2.0

Mod

class Mod(expression1, expression2, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Mod
>>> Vector.objects.create(x=5.4, y=2.3)
>>> vector = Vector.objects.annotate(mod=Mod("x", "y")).get()
>>> vector.mod
0.8

Pi

class Pi(**extra) [исходный код]

Возвращает значение математической константы π.

Power

class Power(expression1, expression2, **extra) [исходный код]

Принимает два числовых поля или выражения и возвращает значение первого в степени, заданной вторым.

Пример использования:

>>> from django.db.models.functions import Power
>>> Vector.objects.create(x=2, y=-2)
>>> vector = Vector.objects.annotate(power=Power("x", "y")).get()
>>> vector.power
0.25

Radians

class Radians(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Radians
>>> Vector.objects.create(x=-90, y=180)
>>> vector = Vector.objects.annotate(x_r=Radians("x"), y_r=Radians("y")).get()
>>> vector.x_r, vector.y_r
(-1.5707963267948966, 3.141592653589793)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Radians
>>> FloatField.register_lookup(Radians)
>>> # Get vectors whose radians are less than 1
>>> vectors = Vector.objects.filter(x__radians__lt=1, y__radians__lt=1)

Random

class Random(**extra) [исходный код]

Возвращает случайное значение в диапазоне 0.0 ≤ x < 1.0.

Round

class Round(expression, precision=0, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Round
>>> Vector.objects.create(x=5.4, y=-2.37)
>>> vector = Vector.objects.annotate(x_r=Round("x"), y_r=Round("y", precision=1)).get()
>>> vector.x_r, vector.y_r
(5.0, -2.4)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Round
>>> FloatField.register_lookup(Round)
>>> # Get vectors whose round() is less than 20
>>> vectors = Vector.objects.filter(x__round__lt=20, y__round__lt=20)

Sign

class Sign(expression, **extra) [исходный код]

Возвращает знак (-1, 0, 1) числового поля или выражения.

Пример использования:

>>> from django.db.models.functions import Sign
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_sign=Sign("x"), y_sign=Sign("y")).get()
>>> vector.x_sign, vector.y_sign
(1, -1)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Sign
>>> FloatField.register_lookup(Sign)
>>> # Get vectors whose signs of components are less than 0.
>>> vectors = Vector.objects.filter(x__sign__lt=0, y__sign__lt=0)

Sin

class Sin(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Sin
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_sin=Sin("x"), y_sin=Sin("y")).get()
>>> vector.x_sin, vector.y_sin
(-0.7727644875559871, -0.7457052121767203)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Sin
>>> FloatField.register_lookup(Sin)
>>> # Get vectors whose sin() is less than 0
>>> vectors = Vector.objects.filter(x__sin__lt=0, y__sin__lt=0)

Sqrt

class Sqrt(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Sqrt
>>> Vector.objects.create(x=4.0, y=12.0)
>>> vector = Vector.objects.annotate(x_sqrt=Sqrt("x"), y_sqrt=Sqrt("y")).get()
>>> vector.x_sqrt, vector.y_sqrt
(2.0, 3.46410)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Sqrt
>>> FloatField.register_lookup(Sqrt)
>>> # Get vectors whose sqrt() is less than 5
>>> vectors = Vector.objects.filter(x__sqrt__lt=5, y__sqrt__lt=5)

Tan

class Tan(expression, **extra) [исходный код]

Возвращает тангенс числового поля или выражения.

Пример использования:

>>> from django.db.models.functions import Tan
>>> Vector.objects.create(x=0, y=12)
>>> vector = Vector.objects.annotate(x_tan=Tan("x"), y_tan=Tan("y")).get()
>>> vector.x_tan, vector.y_tan
(0.0, -0.6358599286615808)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Tan
>>> FloatField.register_lookup(Tan)
>>> # Get vectors whose tangent is less than 0
>>> vectors = Vector.objects.filter(x__tan__lt=0, y__tan__lt=0)

Текстовые функции

Chr

class Chr(expression, **extra) [исходный код]

Принимает числовое поле или выражение и возвращает текстовое представление выражения в виде одного символа. Работает так же, как функция chr() в Python.

Как и Length, её можно зарегистрировать как преобразование для IntegerField. Имя поиска по умолчанию — chr.

Пример использования:

>>> from django.db.models.functions import Chr
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.filter(name__startswith=Chr(ord("M"))).get()
>>> print(author.name)
Margaret Smith

Concat

class Concat(*expressions, **extra) [исходный код]

Принимает список как минимум из двух текстовых полей или выражений и возвращает объединённый текст. Каждый аргумент должен иметь текстовый или символьный тип. Если вы хотите объединить TextField() с CharField(), обязательно укажите Django, что output_field должно быть TextField(). При объединении Value, как в примере ниже, также необходимо указать output_field.

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

Пример использования:

>>> # Get the display name as "name (goes_by)"
>>> from django.db.models import CharField, Value as V
>>> from django.db.models.functions import Concat
>>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
>>> author = Author.objects.annotate(
...     screen_name=Concat("name", V(" ("), "goes_by", V(")"), output_field=CharField())
... ).get()
>>> print(author.screen_name)
Margaret Smith (Maggie)

Left

class Left(expression, length, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Left
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(first_initial=Left("name", 1)).get()
>>> print(author.first_initial)
M

Length

class Length(expression, **extra) [исходный код]

Принимает одно текстовое поле или выражение и возвращает количество символов в значении. Если выражение равно null, длина также будет равна null.

Пример использования:

>>> # Get the length of the name and goes_by fields
>>> from django.db.models.functions import Length
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(
...     name_length=Length("name"), goes_by_length=Length("goes_by")
... ).get()
>>> print(author.name_length, author.goes_by_length)
(14, None)

Её также можно зарегистрировать как преобразование. Например:

>>> from django.db.models import CharField
>>> from django.db.models.functions import Length
>>> CharField.register_lookup(Length)
>>> # Get authors whose name is longer than 7 characters
>>> authors = Author.objects.filter(name__length__gt=7)

Lower

class Lower(expression, **extra) [исходный код]

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

Её также можно зарегистрировать как преобразование, как описано в разделе Length.

Пример использования:

>>> from django.db.models.functions import Lower
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_lower=Lower("name")).get()
>>> print(author.name_lower)
margaret smith

LPad

class LPad(expression, length, fill_text=Value(' '), **extra) [исходный код]

Возвращает значение заданного текстового поля или выражения, дополненное слева символами fill_text до длины length символов. По умолчанию fill_text — пробел.

Пример использования:

>>> from django.db.models import Value
>>> from django.db.models.functions import LPad
>>> Author.objects.create(name="John", alias="j")
>>> Author.objects.update(name=LPad("name", 8, Value("abc")))
1
>>> print(Author.objects.get(alias="j").name)
abcaJohn

LTrim

class LTrim(expression, **extra) [исходный код]

Работает аналогично Trim, но удаляет только начальные пробелы.

MD5

class MD5(expression, **extra) [исходный код]

Принимает одно текстовое поле или выражение и возвращает хеш MD5 строки.

Её также можно зарегистрировать как преобразование, как описано в разделе Length.

Пример использования:

>>> from django.db.models.functions import MD5
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_md5=MD5("name")).get()
>>> print(author.name_md5)
749fb689816b2db85f5b169c2055b247

Ord

class Ord(expression, **extra) [исходный код]

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

Её также можно зарегистрировать как преобразование, как описано в разделе Length. Имя поиска по умолчанию — ord.

Пример использования:

>>> from django.db.models.functions import Ord
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_code_point=Ord("name")).get()
>>> print(author.name_code_point)
77

Repeat

class Repeat(expression, number, **extra) [исходный код]

Возвращает значение заданного текстового поля или выражения, повторённое number раз.

Пример использования:

>>> from django.db.models.functions import Repeat
>>> Author.objects.create(name="John", alias="j")
>>> Author.objects.update(name=Repeat("name", 3))
1
>>> print(Author.objects.get(alias="j").name)
JohnJohnJohn

Replace

class Replace(expression, text, replacement=Value(''), **extra) [исходный код]

Заменяет все вхождения text на replacement в expression. По умолчанию заменой служит пустая строка. Аргументы функции чувствительны к регистру.

Пример использования:

>>> from django.db.models import Value
>>> from django.db.models.functions import Replace
>>> Author.objects.create(name="Margaret Johnson")
>>> Author.objects.create(name="Margaret Smith")
>>> Author.objects.update(name=Replace("name", Value("Margaret"), Value("Margareth")))
2
>>> Author.objects.values("name")
<QuerySet [{'name': 'Margareth Johnson'}, {'name': 'Margareth Smith'}]>

Reverse

class Reverse(expression, **extra) [исходный код]

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

Её также можно зарегистрировать как преобразование, как описано в разделе Length. Имя поиска по умолчанию — reverse.

Пример использования:

>>> from django.db.models.functions import Reverse
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(backward=Reverse("name")).get()
>>> print(author.backward)
htimS teragraM

Right

class Right(expression, length, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Right
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(last_letter=Right("name", 1)).get()
>>> print(author.last_letter)
h

RPad

class RPad(expression, length, fill_text=Value(' '), **extra) [исходный код]

Работает аналогично LPad, но дополняет строку справа.

RTrim

class RTrim(expression, **extra) [исходный код]

Работает аналогично Trim, но удаляет только конечные пробелы.

SHA1, SHA224, SHA256, SHA384 и SHA512

class SHA1(expression, **extra) [исходный код]
class SHA224(expression, **extra) [исходный код]
class SHA256(expression, **extra) [исходный код]
class SHA384(expression, **extra) [исходный код]
class SHA512(expression, **extra) [исходный код]

Принимает одно текстовое поле или выражение и возвращает соответствующий хеш строки.

Их также можно зарегистрировать как преобразования, как описано в разделе Length.

Пример использования:

>>> from django.db.models.functions import SHA1
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_sha1=SHA1("name")).get()
>>> print(author.name_sha1)
b87efd8a6c991c390be5a68e8a7945a7851c7e5c

PostgreSQL

Необходимо установить расширение pgcrypto. Для его установки можно использовать операцию миграции CryptoExtension.

Oracle

Oracle не поддерживает функцию SHA224.

StrIndex

class StrIndex(string, substring, **extra) [исходный код]

Возвращает положительное целое число, соответствующее позиции (с нумерацией от 1) первого вхождения substring внутри string, или 0, если substring не найдено.

Пример использования:

>>> from django.db.models import Value as V
>>> from django.db.models.functions import StrIndex
>>> Author.objects.create(name="Margaret Smith")
>>> Author.objects.create(name="Smith, Margaret")
>>> Author.objects.create(name="Margaret Jackson")
>>> Author.objects.filter(name="Margaret Jackson").annotate(
...     smith_index=StrIndex("name", V("Smith"))
... ).get().smith_index
0
>>> authors = Author.objects.annotate(smith_index=StrIndex("name", V("Smith"))).filter(
...     smith_index__gt=0
... )
<QuerySet [<Author: Margaret Smith>, <Author: Smith, Margaret>]>

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

В MySQL сопоставление таблицы базы данных определяет, чувствительны ли сравнения строк (например, expression и substring этой функции) к регистру. По умолчанию сравнения не чувствительны к регистру.

Substr

class Substr(expression, pos, length=None, **extra) [исходный код]

Возвращает подстроку длиной length из поля или выражения, начиная с позиции pos. Нумерация позиций начинается с 1, поэтому позиция должна быть больше 0. Если length равно None, возвращается оставшаяся часть строки.

Пример использования:

>>> # Set the alias to the first 5 characters of the name as lowercase
>>> from django.db.models.functions import Lower, Substr
>>> Author.objects.create(name="Margaret Smith")
>>> Author.objects.update(alias=Lower(Substr("name", 1, 5)))
1
>>> print(Author.objects.get(name="Margaret Smith").alias)
marga

Trim

class Trim(expression, **extra) [исходный код]

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

Пример использования:

>>> from django.db.models.functions import Trim
>>> Author.objects.create(name="  John  ", alias="j")
>>> Author.objects.update(name=Trim("name"))
1
>>> print(Author.objects.get(alias="j").name)
John

Upper

class Upper(expression, **extra) [исходный код]

Принимает одно текстовое поле или выражение и возвращает его представление в верхнем регистре.

Её также можно зарегистрировать как преобразование, как описано в разделе Length.

Пример использования:

>>> from django.db.models.functions import Upper
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_upper=Upper("name")).get()
>>> print(author.name_upper)
MARGARET SMITH

Оконные функции

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

CumeDist

class CumeDist(*expressions, **extra) [исходный код]

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

DenseRank

class DenseRank(*expressions, **extra) [исходный код]

Аналогично Rank, но без пропусков в рангах.

FirstValue

class FirstValue(expression, **extra) [исходный код]

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

Lag

class Lag(expression, offset=1, default=None, **extra) [исходный код]

Вычисляет значение со смещением offset и возвращает default, если строки по этому смещению нет.

default должен иметь тот же тип, что и expression, однако это проверяется только базой данных, а не Python.

MariaDB и default

MariaDB не поддерживает параметр default.

LastValue

class LastValue(expression, **extra) [исходный код]

Подобно FirstValue, вычисляет последнее значение в заданной рамке.

Lead

class Lead(expression, offset=1, default=None, **extra) [исходный код]

Вычисляет следующее значение в заданной рамке. И offset, и default вычисляются относительно текущей строки.

default должен иметь тот же тип, что и expression, однако это проверяется только базой данных, а не Python.

MariaDB и default

MariaDB не поддерживает параметр default.

NthValue

class NthValue(expression, nth=1, **extra) [исходный код]

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

В разных базах данных отсутствующее значение для n-й строки может обрабатываться по-разному. Например, Oracle возвращает пустую строку вместо None для выражений, основанных на символьных данных. Django не выполняет преобразования в таких случаях.

Ntile

class Ntile(num_buckets=1, **extra) [исходный код]

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

PercentRank

class PercentRank(*expressions, **extra) [исходный код]

Вычисляет относительный ранг строк в рамке. Это вычисление эквивалентно следующему:

(rank - 1) / (total rows - 1)

В таблице ниже показан расчёт относительного ранга строки:

№ строки

Значение

Ранг

Расчёт

Относительный ранг

1

15

1

(1-1)/(7-1)

0.0000

2

20

2

(2-1)/(7-1)

0.1666

3

20

2

(2-1)/(7-1)

0.1666

4

20

2

(2-1)/(7-1)

0.1666

5

30

5

(5-1)/(7-1)

0.6666

6

30

5

(5-1)/(7-1)

0.6666

7

40

7

(7-1)/(7-1)

1.0000

Rank

class Rank(*expressions, **extra) [исходный код]

Подобно RowNumber, эта функция присваивает строкам ранг в окне. Вычисленный ранг содержит пропуски. Используйте DenseRank, чтобы вычислить ранг без пропусков.

RowNumber

class RowNumber(*expressions, **extra) [исходный код]

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

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/6.0/ref/models/database-functions/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API