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

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

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

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, Value as V
>>> 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
>>> aggregated = Author.objects.aggregate(
...    combined_age=Coalesce(Sum('age'), V(0)),
...    combined_age_default=Sum('age'))
>>> print(aggregated['combined_age'])
0
>>> print(aggregated['combined_age_default'])
None

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

Значение 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)[исходный код]
New in Django Development version.

Принимает выражение и имя 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, если вы знаете разумное минимальное значение по умолчанию.

JSONObject

class JSONObject(**fields)[исходный код]
New in Django Development version.

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

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 convention эта функция возвращает пустую строку вместо 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, обычно предоставляемый pytz, может быть передан для извлечения значения в определенном часовом поясе.

Учитывая время даты 2015-06-15 23:30:01.000321+00:00, встроенные lookup_names возвращаются:

  • «год»: 2015
  • «iso_year»: 2015
  • «квартал»: 2
  • «месяц»: 6
  • «день»: 15
  • «неделя»: 25
  • «week_day»: 2
  • «iso_week_day»: 1
  • «час»: 23
  • «минута»: 30
  • «second»: 1

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

  • «день»: 16
  • «week_day»: 3
  • «iso_week_day»: 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)[исходный код]
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)[исходный код]
New in Django 3.1.

Возвращает день недели по стандарту 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.

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

>>> from datetime import datetime
>>> from django.utils import 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 могут быть использованы и для DateTimeFields .

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 datetime
>>> from django.utils import 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, то время даты хранится в базе данных в UTC. Если в Django активен другой часовой пояс, то перед извлечением значения дататайм конвертируется в этот часовой пояс. В приведенном ниже примере преобразование выполняется в часовой пояс Мельбурна (UTC +10:00), что изменяет возвращаемые значения дня, дня недели и часа:

>>> import pytz
>>> melb = pytz.timezone('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 pytz
>>> melb = pytz.timezone('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.

Trunc

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

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

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

Trunc принимает один expression, представляющий DateField, TimeField или DateTimeField, kind, представляющий часть даты или времени, и output_field, который является либо DateTimeField(), либо TimeField(), либо DateField(). Он возвращает время, дату или время в зависимости от output_field, при этом поля до kind устанавливаются в минимальное значение. Если output_field опущен, то по умолчанию возвращается output_field из expression. Подкласс tzinfo, обычно предоставляемый pytz, может быть передан для усечения значения в определенном часовом поясе.

Параметр is_dst указывает, следует ли pytz интерпретировать несуществующие и неоднозначные даты в летнее время. По умолчанию (когда is_dst=None), pytz вызывает исключение для таких дат.

Учитывая время даты 2015-06-15 14:30:50.000321+00:00, встроенные kinds возвращаются:

  • «год»: 2015-01-01 00:00:00+00:00
  • «квартал»: 2015-04-01 00:00:00+00:00
  • «месяц»: 2015-06-01 00:00:00+00:00
  • «неделя»: 2015-06-15 00:00:00+00:00
  • «день»: 2015-06-15 00:00:00+00:00
  • «час»: 2015-06-15 14:00:00+00:00
  • «минута»: 2015-06-15 14:30:00+00:00
  • «второй»: 2015-06-15 14:30:50+00:00

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

  • «год»: 2015-01-01 00:00:00+11:00
  • «квартал»: 2015-04-01 00:00:00+10:00
  • «месяц»: 2015-06-01 00:00:00+10:00
  • «неделя»: 2015-06-16 00:00:00+10:00
  • «день»: 2015-06-16 00:00:00+10:00
  • «час»: 2015-06-16 00:00:00+10:00
  • «минута»: 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, is_dst=None, **extra)[исходный код]
kind = 'year'
class TruncMonth(expression, output_field=None, tzinfo=None, is_dst=None, **extra)[исходный код]
kind = 'month'
class TruncWeek(expression, output_field=None, tzinfo=None, is_dst=None, **extra)[исходный код]

Усечение до полуночи в понедельник недели.

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

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

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

>>> from datetime import datetime
>>> from django.db.models import Count
>>> from django.db.models.functions import TruncMonth, TruncYear
>>> from django.utils import timezone
>>> 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 pytz
>>> melb = pytz.timezone('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()
Changed in Django Development version:

Был добавлен параметр tzinfo.

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

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

Был добавлен параметр tzinfo.

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

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

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

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

>>> from datetime import date, datetime
>>> from django.db.models import Count
>>> from django.db.models.functions import (
...     TruncDate, TruncDay, TruncHour, TruncMinute, TruncSecond,
... )
>>> from django.utils import timezone
>>> import pytz
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
>>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
>>> melb = pytz.timezone('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=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
 'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
 'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=<UTC>),
 'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=<UTC>)
}

TimeField усечение

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

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

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

>>> from datetime import datetime
>>> from django.db.models import Count, TimeField
>>> from django.db.models.functions import TruncHour
>>> from django.utils import timezone
>>> 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 pytz
>>> melb = pytz.timezone('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

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

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

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)[исходный код]

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

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

>>> 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)[исходный код]
New in Django Development version.

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

Round

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

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

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

>>> from django.db.models.functions import Round
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_r=Round('x'), y_r=Round('y')).get()
>>> vector.x_r, vector.y_r
(5.0, -2.0)

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

>>> 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)[исходный код]

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

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

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

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

>>> # 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 для первого символа этого выражения. Работает аналогично функции 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)[исходный код]

Возвращает значение заданного текстового поля или выражения, повторенное 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 extension. Для его установки можно использовать операцию миграции 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 параметр collation таблицы базы данных определяет, являются ли сравнения строк (такие как 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 doesn’t support параметр default.

LastValue

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

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

Lead

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

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

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

MariaDB и default

MariaDB doesn’t support параметр default.

NthValue

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

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

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

Ntile

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

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

PercentRank

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

Вычисляет процентильный ранг строк в предложении frame. Это вычисление эквивалентно оценке:

(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)[исходный код]

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

Вернуться на верх