Функции базы данных
Классы, описанные ниже, предоставляют способ для пользователей использовать функции, предоставляемые базой данных в качестве аннотаций, агрегаций или фильтров в 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
>>> Value.objects.create(integer=4)
>>> value = Value.objects.annotate(as_float=Cast('integer', FloatField())).get()
>>> print(value.as_float)
4.0
Coalesce
-
class Coalesce(*expressions, **extra)[source]
Принимает список из как минимум двух имён полей или выражений и возвращает первое ненулевое значение (обратите внимание, что пустая строка не считается нулевым значением). Каждый аргумент должен быть одного типа, поэтому смешивание текста и чисел приведёт к ошибке базы данных.
Примеры использования:
>>> # 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()))
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 , если известно разумное максимальное значение в качестве значения по умолчанию.
Функции даты
В примерах каждой функции мы будем использовать следующую модель:
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, обычно предоставляемый pytz, может быть передан для извлечения значения в определённой часовой зоне.
Была добавлена поддержка DurationField.
Для даты-времени 2015-06-15 23:30:01.000321+00:00, встроенные lookup_name возвращают:
- “year”: 2015
- “quarter”: 2
- “month”: 6
- “day”: 15
- “week”: 25
- “week_day”: 2
- “hour”: 23
- “minute”: 30
- “second”: 1
Если в Django активна другая часовая зона, например, Australia/Melbourne, то дата-время преобразуется в эту часовую зону перед извлечением значения. Смещение часовой зоны для Мельбурна в примере даты выше составляет +10:00. Значения, возвращаемые при активации этой часовой зоны, будут такими же, как выше, за исключением:
- “day”: 16
- “week_day”: 3
- “hour”: 9
week_day значения
Значение week_day lookup_type вычисляется по-другому, чем в большинстве баз данных и в стандартных функциях Python. Эта функция вернёт 1 для воскресенья, 2 для понедельника, до 7 для субботы.
Эквивалентное вычисление в Python:
>>> from datetime import datetime >>> dt = datetime(2015, 6, 15) >>> (dt.isoweekday() % 7) + 1 2
week значения
Значение week lookup_type рассчитывается на основе ISO-8601, т.е. неделя начинается с понедельника. Первая неделя года — та, которая содержит первый четверг года, т.е. в первой неделе большинство (четыре или более) дней находится в этом году. Возвращаемое значение находится в диапазоне от 1 до 52 или 53.
Каждому lookup_name выше соответствует соответствующий подкласс Extract, который, как правило, следует использовать вместо более громоздкого эквивалента, например, используйте ExtractYear(...) вместо Extract(..., lookup_name='year').
Пример использования:
>>> from datetime import datetime
>>> from django.db.models.functions import Extract
>>> start = datetime(2015, 6, 15)
>>> end = datetime(2015, 7, 2)
>>> Experiment.objects.create(
... start_datetime=start, start_date=start.date(),
... end_datetime=end, end_date=end.date())
>>> # Add the experiment start year as a field in the QuerySet.
>>> experiment = Experiment.objects.annotate(
... start_year=Extract('start_datetime', 'year')).get()
>>> experiment.start_year
2015
>>> # How many experiments completed in the same year in which they started?
>>> Experiment.objects.filter(
... start_datetime__year=Extract('end_datetime', 'year')).count()
1
DateField функции извлечения
-
class ExtractYear(expression, tzinfo=None, **extra)[source] -
-
lookup_name = '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 ExtractWeek(expression, tzinfo=None, **extra)[source] -
Новое в Django 1.11.
-
lookup_name = 'week'
-
-
class ExtractQuarter(expression, tzinfo=None, **extra)[source] -
Новое в Django 2.0.
-
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,
... ExtractWeekDay, 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'),
... quarter=ExtractQuarter('start_date'),
... month=ExtractMonth('start_date'),
... week=ExtractWeek('start_date'),
... day=ExtractDay('start_date'),
... weekday=ExtractWeekDay('start_date'),
... ).values('year', 'quarter', 'month', 'week', 'day', 'weekday').get(
... end_date__year=ExtractYear('start_date'),
... )
{'year': 2015, 'quarter': 2, 'month': 6, 'week': 25, 'day': 15, 'weekday': 2}
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
>>> from django.utils import timezone
>>> from django.db.models.functions import (
... ExtractDay, ExtractHour, ExtractMinute, ExtractMonth,
... ExtractQuarter, ExtractSecond, ExtractWeek, ExtractWeekDay,
... 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'),
... quarter=ExtractQuarter('start_datetime'),
... month=ExtractMonth('start_datetime'),
... week=ExtractWeek('start_datetime'),
... day=ExtractDay('start_datetime'),
... weekday=ExtractWeekDay('start_datetime'),
... hour=ExtractHour('start_datetime'),
... minute=ExtractMinute('start_datetime'),
... second=ExtractSecond('start_datetime'),
... ).values(
... 'year', 'month', 'week', 'day', 'weekday', 'hour', 'minute', 'second',
... ).get(end_datetime__year=ExtractYear('start_datetime'))
{'year': 2015, 'quarter': 2, 'month': 6, 'week': 25, 'day': 15, 'weekday': 2,
'hour': 23, 'minute': 30, 'second': 1}
Когда USE_TZ равен True, значения datetime сохраняются в базе данных в формате UTC. Если в Django активен другой часовой пояс, datetime преобразуется в этот часовой пояс перед извлечением значения. Пример ниже преобразует в часовой пояс Мельбурна (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'),
... hour=ExtractHour('start_datetime'),
... ).values('day', 'weekday', 'hour').get(
... end_datetime__year=ExtractYear('start_datetime'),
... )
{'day': 16, 'weekday': 3, '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),
... hour=ExtractHour('start_datetime', tzinfo=melb),
... ).values('day', 'weekday', 'hour').get(
... end_datetime__year=ExtractYear('start_datetime'),
... )
{'day': 16, 'weekday': 3, '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.
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(). Он возвращает datetime, date или time в зависимости от output_field, с полями до kind, установленными в минимальное значение. Если output_field опущено, оно по умолчанию будет равно output_field expression. Подкласс tzinfo, обычно предоставляемый pytz, может быть передан для округления значения в определенном часовом поясе.
Учитывая datetime 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
- “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, то datetime преобразуется в новый часовой пояс до округления. Смещение часового пояса для Мельбурна в примере даты выше составляет +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
- “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 TruncQuarter(expression, output_field=None, tzinfo=None, **extra)[source] -
Новое в Django 2.0.
-
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, **extra)[source] -
-
lookup_name = 'date'
-
output_field = DateField()
-
TruncDate преобразует expression в дату, а не используя встроенную SQL функцию округления. Он также зарегистрирован как преобразование в DateTimeField как __date.
-
class TruncTime(expression, **extra)[source]
-
lookup_name = 'time'
-
output_field = TimeField()
TruncTime преобразует expression в время, а не используя встроенную SQL функцию округления. Он также зарегистрирован как преобразование в 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 и позволяют группировать или фильтровать datetime с меньшей точностью. 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, **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('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
Функции текста
Concat
-
class Concat(*expressions, **extra)[source]
Принимает список из как минимум двух текстовых полей или выражений и возвращает конкатенированный текст. Каждый аргумент должен быть типа текст или 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)
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, '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
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, коллирование таблицы базы данных определяет, являются ли строковые сравнения (например, 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
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.
LastValue
-
class LastValue(expression, **extra)[source]
Аналогично FirstValue, вычисляет последнее значение в заданном фрагменте кадра.
Lead
-
class Lead(expression, offset=1, default=None, **extra)[source]
Вычисляет ведущее значение в заданном кадре. И offset, и default вычисляются относительно текущей строки.
default должно иметь тот же тип, что и expression, однако это проверяется только базой данных, а не Python.
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/2.0/ref/models/database-functions/