Spec-Zone.ru › Django 5.2

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

Класс, описанные ниже, предоставляют пользователям возможность использовать функции, предоставляемые основной базой данных, в качестве аннотаций, агрегаций или фильтров в 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) [source]

Принудительно устанавливает тип результата 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) [source]

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

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

>>> # 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) [source]

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

Например, для фильтрации без учета регистра в 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) [source]

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

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

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

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

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

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

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

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

NullIf

class NullIf(expression1, expression2) [source]

Принимает два выражения и возвращает 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) [source]

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

Принимает 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 возвращают:

  • “год”: 2015
  • “год_iso”: 2015
  • “квартал”: 2
  • “месяц”: 6
  • “день”: 15
  • “неделя”: 25
  • “день_недели”: 2
  • “день_недели_iso”: 1
  • “час”: 23
  • “минута”: 30
  • “секунда”: 1

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

  • “день”: 16
  • “день_недели”: 3
  • “день_недели_iso”: 2
  • “час”: 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) [source]
lookup_name = 'year'
class ExtractIsoYear(expression, tzinfo=None, **extra) [source]

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

lookup_name = 'iso_year'
class ExtractMonth(expression, tzinfo=None, **extra) [source]
lookup_name = 'month'
class ExtractDay(expression, tzinfo=None, **extra) [source]
lookup_name = 'day'
class ExtractWeekDay(expression, tzinfo=None, **extra) [source]
lookup_name = 'week_day'
class ExtractIsoWeekDay(expression, tzinfo=None, **extra) [source]

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

lookup_name = 'iso_week_day'
class ExtractWeek(expression, tzinfo=None, **extra) [source]
lookup_name = 'week'
class ExtractQuarter(expression, tzinfo=None, **extra) [source]
lookup_name = 'quarter'

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

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

>>> from datetime import datetime, timezone
>>> from django.db.models.functions import (
...     ExtractDay,
...     ExtractMonth,
...     ExtractQuarter,
...     ExtractWeek,
...     ExtractIsoWeekDay,
...     ExtractWeekDay,
...     ExtractIsoYear,
...     ExtractYear,
... )
>>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=timezone.utc)
>>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.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 извлечения

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

class ExtractHour(expression, tzinfo=None, **extra) [source]
lookup_name = 'hour'
class ExtractMinute(expression, tzinfo=None, **extra) [source]
lookup_name = 'minute'
class ExtractSecond(expression, tzinfo=None, **extra) [source]
lookup_name = 'second'

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

DateTimeField примеры:

>>> from datetime import datetime, timezone
>>> 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=timezone.utc)
>>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.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, datetime хранятся в базе данных в UTC. Если в Django активен другой часовой пояс, datetime преобразуется в этот часовой пояс перед извлечением значения. В примере ниже происходит преобразование в часовой пояс Мельбурна (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 [source]

Возвращает текущую дату и время сервера базы данных при выполнении запроса, обычно используя 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) [source]

Обрезает дату до значимого компонента.

Если вам нужно только знать, произошло ли что-то в определенном году, часе или дне, а не точной секунде, то 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) [source]
kind = 'year'
class TruncMonth(expression, output_field=None, tzinfo=None, **extra) [source]
kind = 'month'
class TruncWeek(expression, output_field=None, tzinfo=None, **extra) [source]

Обрезает до полуночи в понедельник недели.

kind = 'week'
class TruncQuarter(expression, output_field=None, tzinfo=None, **extra) [source]
kind = 'quarter'

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

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

>>> from datetime import datetime, timezone
>>> from django.db.models import Count
>>> from django.db.models.functions import TruncMonth, TruncYear
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
>>> start2 = datetime(2015, 6, 15, 14, 40, 2, 123, tzinfo=timezone.utc)
>>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=timezone.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) [source]
lookup_name = 'date'
output_field = DateField()

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

class TruncTime(expression, tzinfo=None, **extra) [source]
lookup_name = 'time'
output_field = TimeField()

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

class TruncDay(expression, output_field=None, tzinfo=None, **extra) [source]
kind = 'day'
class TruncHour(expression, output_field=None, tzinfo=None, **extra) [source]
kind = 'hour'
class TruncMinute(expression, output_field=None, tzinfo=None, **extra) [source]
kind = 'minute'
class TruncSecond(expression, output_field=None, tzinfo=None, **extra) [source]
kind = 'second'

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

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

>>> from datetime import date, datetime, timezone
>>> 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=timezone.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=timezone.utc),
 'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=timezone.utc)
}

TimeField усечение

классTruncHour(expression, output_field=None, tzinfo=None, **extra)[source]
kind = 'hour'
классTruncMinute(expression, output_field=None, tzinfo=None, **extra)[source]
kind = 'minute'
классTruncSecond(expression, output_field=None, tzinfo=None, **extra)[source]
kind = 'second'

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

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

>>> from datetime import datetime, timezone
>>> from django.db.models import Count, TimeField
>>> from django.db.models.functions import TruncHour
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
>>> start2 = datetime(2014, 6, 15, 14, 40, 2, 123, tzinfo=timezone.utc)
>>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=timezone.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) [source]

Принимает список имён полей или выражений и возвращает массив 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) [source]

Принимает список пар ключ-значение и возвращает объект 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) [source]

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

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

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

Возвращает арккосинус числового поля или выражения. Значение выражения должно находиться в диапазоне от -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) [source]

Возвращает арксинус числового поля или выражения. Значение выражения должно находиться в диапазоне от -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) [source]

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

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

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

Возвращает арктангенс 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) [source]

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

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

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

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

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

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

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

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

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

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

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

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

Возвращает значение 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) [source]

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

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

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

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

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

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

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

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

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

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

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

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

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

Power

class Power(expression1, expression2, **extra) [source]

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

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

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

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

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

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

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

Round

class Round(expression, precision=0, **extra) [source]

Округляет числовое поле или выражение до 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) [source]

Возвращает знак (-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) [source]

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

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

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

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

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

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

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

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

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

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

Как и 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) [source]

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

Эта функция никогда не вернёт 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) [source]

Возвращает первые 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) [source]

Принимает одно текстовое поле или выражение и возвращает количество символов в значении. Если выражение 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) [source]

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

Она также может быть зарегистрирована как преобразование, как описано в 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) [source]

Возвращает значение данного текстового поля или выражения, дополненного слева 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) [source]

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

MD5

class MD5(expression, **extra) [source]

Принимает одно текстовое поле или выражение и возвращает 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) [source]

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

Также может быть зарегистрирована как преобразование, как описано в 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) [source]

Возвращает значение данного текстового поля или выражения, повторённое 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) [source]

Заменяет все вхождения 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) [source]

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

Также может быть зарегистрирована как преобразование, как описано в 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) [source]

Возвращает последние 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) [source]

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

RTrim

class RTrim(expression, **extra) [source]

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

SHA1, SHA224, SHA256, SHA384, и SHA512

class SHA1(expression, **extra) [source]
class SHA224(expression, **extra) [source]
class SHA256(expression, **extra) [source]
class SHA384(expression, **extra) [source]
class SHA512(expression, **extra) [source]

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

Их также можно зарегистрировать как преобразования, как описано в 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) [source]

Возвращает положительное целое число, соответствующее 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, кодировка таблицы базы данных collation определяет, являются ли строковые сравнения (такие как expression и substring этой функции) регистрозависимыми. Сравнения по умолчанию регистронезависимые.

Substr

class Substr(expression, pos, length=None, **extra) [source]

Возвращает подстроку длины 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) [source]

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

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

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

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

Также можно зарегистрировать его как преобразование, как описано в 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) [source]

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

DenseRank

class DenseRank(*expressions, **extra) [source]

Эквивалентно Rank, но без пробелов.

FirstValue

class FirstValue(expression, **extra) [source]

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

Lag

class Lag(expression, offset=1, default=None, **extra) [source]

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

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

MariaDB и default

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

LastValue

class LastValue(expression, **extra) [source]

Аналогично FirstValue, вычисляет последнее значение в заданном фрагменте.

Lead

class Lead(expression, offset=1, default=None, **extra) [source]

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

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

MariaDB и default

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

NthValue

class NthValue(expression, nth=1, **extra) [source]

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

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

Ntile

class Ntile(num_buckets=1, **extra) [source]

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

PercentRank

class PercentRank(*expressions, **extra) [source]

Вычисляет относительный ранг строк во фрагменте. Это вычисление эквивалентно оценке:

(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) [source]

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

RowNumber

class RowNumber(*expressions, **extra) [source]

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

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

Spec-Zone.ru

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