数据库函数 — Django 文档
数据库函数
下面记录的类为用户提供了一种使用底层数据库提供的函数作为 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)
我们通常不建议为 CharField
允许 null=True
,因为这允许该字段有两个“空值”,但这对于下面的 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
警告
除非显式转换为正确的数据库类型,否则在 MySQL 上传递给 Coalesce
的 Python 值可能会转换为不正确的类型:
>>> 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)
接受至少包含两个字段名称或表达式的列表并返回最大值。 每个参数必须是相似的类型,所以混合文本和数字会导致数据库错误。
用法示例:
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
中最新的。
警告
当一个或多个表达式可能是 null
时,Greatest
的行为因数据库而异:
- PostgreSQL:
Greatest
将返回最大的非空表达式,如果所有表达式都是null
,则返回null
。 - SQLite、Oracle 和 MySQL:如果任何表达式为
null
,则Greatest
将返回null
。
如果您知道要作为默认值提供的合理最小值,则可以使用 Coalesce
模拟 PostgreSQL 行为。
Least
- class Least(*expressions, **extra)
接受至少包含两个字段名称或表达式的列表并返回最小值。 每个参数必须是相似的类型,所以混合文本和数字会导致数据库错误。
警告
当一个或多个表达式可能是 null
时,Least
的行为因数据库而异:
- PostgreSQL:
Least
将返回最小的非空表达式,如果所有表达式都是null
,则返回null
。 - SQLite、Oracle 和 MySQL:如果任何表达式为
null
,则Least
将返回null
。
如果您知道要提供的合理最大值作为默认值,则可以使用 Coalesce
模拟 PostgreSQL 行为。
日期函数
我们将在每个函数的示例中使用以下模型:
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)
提取日期的一个组成部分作为一个数字。
取一个表示 DateField
、DateTimeField
、TimeField
或 DurationField
和一个 lookup_name
的 expression
,并返回lookup_name
作为 IntegerField
引用的日期的一部分。 Django 通常使用数据库的提取功能,因此您可以使用数据库支持的任何 lookup_name
。 通常由 pytz
提供的 tzinfo
子类可以传递以提取特定时区中的值。
给定日期时间 2015-06-15 23:30:01.000321+00:00
,内置的 lookup_name
s 返回:
- “年”:2015
- “iso_year”:2015
- “季度”:2
- “月”:6
- “天”:15
- “周”:25
- “week_day”:2
- “小时”:23
- “分钟”:30
- “第二个”:1
如果像 Australia/Melbourne
这样的不同时区在 Django 中处于活动状态,则在提取值之前将日期时间转换为时区。 上面示例日期中墨尔本的时区偏移为 +10:00。 此时区处于活动状态时返回的值将与上述相同,除了:
- “天”:16
- “week_day”:3
- “小时”: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)
2.2 版中的新功能。
返回 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 ExtractWeek(expression, tzinfo=None, **extra)
- ;; lookup_name = 'week'
- class ExtractQuarter(expression, tzinfo=None, **extra)
- ;; lookup_name = 'quarter'
这些在逻辑上等同于 Extract('date_field', lookup_name)
。 每个类也是在 DateField
和 DateTimeField
上注册为 __(lookup_name)
的 Transform
,例如 __year
。
由于 DateField
没有时间分量,因此只有处理日期部分的 Extract
子类可以与 DateField
一起使用:
>>> from datetime import datetime
>>> from django.utils import timezone
>>> from django.db.models.functions import (
... ExtractDay, ExtractMonth, ExtractQuarter, ExtractWeek,
... 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'),
... ).values('year', 'isoyear', 'quarter', 'month', 'week', 'day', 'weekday').get(
... end_date__year=ExtractYear('start_date'),
... )
{'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
'day': 15, 'weekday': 2}
DateTimeField 摘录
除了以下内容之外,上面列出的 DateField
的所有提取物也可以用于 DateTimeField
s 。
- 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)
。 每个类也是一个在 DateTimeField
上注册为 __(lookup_name)
的 Transform
,例如 __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'),
... isoyear=ExtractIsoYear('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', 'isoyear', 'month', 'week', 'day',
... 'weekday', 'hour', 'minute', 'second',
... ).get(end_datetime__year=ExtractYear('start_datetime'))
{'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
'day': 15, 'weekday': 2, 'hour': 23, 'minute': 30, 'second': 1}
当 :setting:`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'),
... 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
返回执行查询时数据库服务器的当前日期和时间,通常使用 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)
将一个日期截断到一个重要的部分。
当您只关心某事是否发生在特定的年、小时或日,而不是确切的秒时,那么 Trunc
(及其子类)可用于过滤或聚合您的数据。 例如,您可以使用 Trunc
来计算每天的销售数量。
Trunc
取单个 expression
,代表一个 DateField
、TimeField
或 DateTimeField
,一个 kind
代表一个日期或时间部分,以及 output_field
是 DateTimeField()
、TimeField()
或 DateField()
。 它根据 output_field
返回日期时间、日期或时间,最多 kind
的字段设置为其最小值。 如果省略output_field
,则默认为expression
的output_field
。 通常由 pytz
提供的 tzinfo
子类可以传递以截断特定时区中的值。
给定日期时间 2015-06-15 14:30:50.000321+00:00
,内置的 kind
s 返回:
- “年”: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
如果像 Australia/Melbourne
这样的不同时区在 Django 中处于活动状态,则日期时间会在值被截断之前转换为新时区。 上面示例日期中墨尔本的时区偏移为 +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
- “第二个”:2015-06-16 00:30:50+10:00
年的偏移量为 +11:00,因为结果过渡到夏令时。
上面的每个 kind
都有一个相应的 Trunc
子类(如下所列),通常应该使用它来代替更冗长的等效项,例如 使用 TruncYear(...)
而不是 Trunc(..., kind='year')
。
子类都定义为转换,但它们没有注册到任何字段,因为明显的查找名称已经被 Extract
子类保留。
用法示例:
>>> from datetime import datetime
>>> from django.db.models import Count, DateTimeField
>>> from django.db.models.functions import Trunc
>>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 30, 50, 321))
>>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 40, 2, 123))
>>> Experiment.objects.create(start_datetime=datetime(2015, 12, 25, 10, 5, 27, 999))
>>> experiments_per_day = Experiment.objects.annotate(
... start_day=Trunc('start_datetime', 'day', output_field=DateTimeField())
... ).values('start_day').annotate(experiments=Count('id'))
>>> for exp in experiments_per_day:
... print(exp['start_day'], exp['experiments'])
...
2015-06-15 00:00:00 2
2015-12-25 00:00:00 1
>>> experiments = Experiment.objects.annotate(
... start_day=Trunc('start_datetime', 'day', output_field=DateTimeField())
... ).filter(start_day=datetime(2015, 6, 15))
>>> for exp in experiments:
... print(exp.start_datetime)
...
2015-06-15 14:30:50.000321
2015-06-15 14:40:02.000123
DateField 截断
- class TruncYear(expression, output_field=None, tzinfo=None, **extra)
- ;; kind = 'year'
- class TruncMonth(expression, output_field=None, tzinfo=None, **extra)
- ;; kind = 'month'
- class TruncWeek(expression, output_field=None, tzinfo=None, **extra)
2.1 版中的新功能。
截断到每周一的午夜。
- kind = 'week'
- class TruncQuarter(expression, output_field=None, tzinfo=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, **extra)
- lookup_name = 'date'
- output_field = DateField()
TruncDate
将 expression
转换为日期,而不是使用内置的 SQL 截断函数。 它也在 DateTimeField
上注册为 __date
的转换。
- class TruncTime(expression, **extra)
- lookup_name = 'time'
- output_field = TimeField()
TruncTime
将 expression
转换为时间,而不是使用内置的 SQL 截断函数。 它也在 DateTimeField
上注册为 __time
的转换。
- class TruncDay(expression, output_field=None, tzinfo=None, **extra)
- ;; kind = 'day'
- class TruncHour(expression, output_field=None, tzinfo=None, **extra)
- ;; kind = 'hour'
- class TruncMinute(expression, output_field=None, tzinfo=None, **extra)
- ;; kind = 'minute'
- class TruncSecond(expression, output_field=None, tzinfo=None, **extra)
- ;; kind = 'second'
这些在逻辑上等同于 Trunc('datetime_field', kind)
。 它们将日期的所有部分截断到 kind
并允许以较低的精度对日期时间进行分组或过滤。 expression
必须有 DateTimeField
的 output_field
。
用法示例:
>>> 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)
- ;; kind = 'hour'
- class TruncMinute(expression, output_field=None, tzinfo=None, **extra)
- ;; kind = 'minute'
- class TruncSecond(expression, output_field=None, tzinfo=None, **extra)
- ;; kind = 'second'
这些在逻辑上等同于 Trunc('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
数学函数
2.2 版中的新功能。
我们将在数学函数示例中使用以下模型:
class Vector(models.Model):
x = models.FloatField()
y = models.FloatField()
Abs
- class Abs(expression, **extra)
返回一个数值字段或表达式的绝对值。
用法示例:
>>> from django.db.models.functions import Abs
>>> Vector.objects.create(x=-0.5, y=1.1)
>>> vector = Vector.objects.annotate(x_abs=Abs('x'), y_abs=Abs('y')).get()
>>> vector.x_abs, vector.y_abs
(0.5, 1.1)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Abs
>>> FloatField.register_lookup(Abs)
>>> # Get vectors inside the unit cube
>>> vectors = Vector.objects.filter(x__abs__lt=1, y__abs__lt=1)
ACos
- class ACos(expression, **extra)
返回数字字段或表达式的反余弦值。 表达式值必须在 -1 到 1 的范围内。
用法示例:
>>> from django.db.models.functions import ACos
>>> Vector.objects.create(x=0.5, y=-0.9)
>>> vector = Vector.objects.annotate(x_acos=ACos('x'), y_acos=ACos('y')).get()
>>> vector.x_acos, vector.y_acos
(1.0471975511965979, 2.6905658417935308)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import ACos
>>> FloatField.register_lookup(ACos)
>>> # Get vectors whose arccosine is less than 1
>>> vectors = Vector.objects.filter(x__acos__lt=1, y__acos__lt=1)
ASin
- class ASin(expression, **extra)
返回数值字段或表达式的反正弦。 表达式值必须在 -1 到 1 的范围内。
用法示例:
>>> from django.db.models.functions import ASin
>>> Vector.objects.create(x=0, y=1)
>>> vector = Vector.objects.annotate(x_asin=ASin('x'), y_asin=ASin('y')).get()
>>> vector.x_asin, vector.y_asin
(0.0, 1.5707963267948966)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import ASin
>>> FloatField.register_lookup(ASin)
>>> # Get vectors whose arcsine is less than 1
>>> vectors = Vector.objects.filter(x__asin__lt=1, y__asin__lt=1)
ATan
- class ATan(expression, **extra)
返回一个数值字段或表达式的正切值。
用法示例:
>>> from django.db.models.functions import ATan
>>> Vector.objects.create(x=3.12, y=6.987)
>>> vector = Vector.objects.annotate(x_atan=ATan('x'), y_atan=ATan('y')).get()
>>> vector.x_atan, vector.y_atan
(1.2606282660069106, 1.428638798133829)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import ATan
>>> FloatField.register_lookup(ATan)
>>> # Get vectors whose arctangent is less than 2
>>> vectors = Vector.objects.filter(x__atan__lt=2, y__atan__lt=2)
ATan2
- class ATan2(expression1, expression2, **extra)
返回 expression1 / expression2
的反正切值。
用法示例:
>>> from django.db.models.functions import ATan2
>>> Vector.objects.create(x=2.5, y=1.9)
>>> vector = Vector.objects.annotate(atan2=ATan2('x', 'y')).get()
>>> vector.atan2
0.9209258773829491
Ceil
- class Ceil(expression, **extra)
返回大于或等于一个数值字段或表达式的最小整数。
用法示例:
>>> from django.db.models.functions import Ceil
>>> Vector.objects.create(x=3.12, y=7.0)
>>> vector = Vector.objects.annotate(x_ceil=Ceil('x'), y_ceil=Ceil('y')).get()
>>> vector.x_ceil, vector.y_ceil
(4.0, 7.0)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Ceil
>>> FloatField.register_lookup(Ceil)
>>> # Get vectors whose ceil is less than 10
>>> vectors = Vector.objects.filter(x__ceil__lt=10, y__ceil__lt=10)
Cos
- class Cos(expression, **extra)
返回一个数值字段或表达式的余弦值。
用法示例:
>>> from django.db.models.functions import Cos
>>> Vector.objects.create(x=-8.0, y=3.1415926)
>>> vector = Vector.objects.annotate(x_cos=Cos('x'), y_cos=Cos('y')).get()
>>> vector.x_cos, vector.y_cos
(-0.14550003380861354, -0.9999999999999986)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Cos
>>> FloatField.register_lookup(Cos)
>>> # Get vectors whose cosine is less than 0.5
>>> vectors = Vector.objects.filter(x__cos__lt=0.5, y__cos__lt=0.5)
Cot
- class Cot(expression, **extra)
返回数值字段或表达式的正切值。
用法示例:
>>> from django.db.models.functions import Cot
>>> Vector.objects.create(x=12.0, y=1.0)
>>> vector = Vector.objects.annotate(x_cot=Cot('x'), y_cot=Cot('y')).get()
>>> vector.x_cot, vector.y_cot
(-1.5726734063976826, 0.642092615934331)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Cot
>>> FloatField.register_lookup(Cot)
>>> # Get vectors whose cotangent is less than 1
>>> vectors = Vector.objects.filter(x__cot__lt=1, y__cot__lt=1)
Degrees
- class Degrees(expression, **extra)
将数值字段或表达式从弧度转换为度。
用法示例:
>>> from django.db.models.functions import Degrees
>>> Vector.objects.create(x=-1.57, y=3.14)
>>> vector = Vector.objects.annotate(x_d=Degrees('x'), y_d=Degrees('y')).get()
>>> vector.x_d, vector.y_d
(-89.95437383553924, 179.9087476710785)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Degrees
>>> FloatField.register_lookup(Degrees)
>>> # Get vectors whose degrees are less than 360
>>> vectors = Vector.objects.filter(x__degrees__lt=360, y__degrees__lt=360)
Exp
- class Exp(expression, **extra)
返回 e
(自然对数底)的数值字段或表达式的幂。
用法示例:
>>> from django.db.models.functions import Exp
>>> Vector.objects.create(x=5.4, y=-2.0)
>>> vector = Vector.objects.annotate(x_exp=Exp('x'), y_exp=Exp('y')).get()
>>> vector.x_exp, vector.y_exp
(221.40641620418717, 0.1353352832366127)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Exp
>>> FloatField.register_lookup(Exp)
>>> # Get vectors whose exp() is greater than 10
>>> vectors = Vector.objects.filter(x__exp__gt=10, y__exp__gt=10)
Floor
- class Floor(expression, **extra)
返回不大于数值字段或表达式的最大整数值。
用法示例:
>>> from django.db.models.functions import Floor
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_floor=Floor('x'), y_floor=Floor('y')).get()
>>> vector.x_floor, vector.y_floor
(5.0, -3.0)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Floor
>>> FloatField.register_lookup(Floor)
>>> # Get vectors whose floor() is greater than 10
>>> vectors = Vector.objects.filter(x__floor__gt=10, y__floor__gt=10)
Ln
- class Ln(expression, **extra)
返回一个数值字段或表达式的自然对数。
用法示例:
>>> from django.db.models.functions import Ln
>>> Vector.objects.create(x=5.4, y=233.0)
>>> vector = Vector.objects.annotate(x_ln=Ln('x'), y_ln=Ln('y')).get()
>>> vector.x_ln, vector.y_ln
(1.6863989535702288, 5.4510384535657)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Ln
>>> FloatField.register_lookup(Ln)
>>> # Get vectors whose value greater than e
>>> vectors = Vector.objects.filter(x__ln__gt=1, y__ln__gt=1)
Log
- class Log(expression1, expression2, **extra)
接受两个数字字段或表达式,并返回第一个字段的对数到第二个字段的基数。
用法示例:
>>> from django.db.models.functions import Log
>>> Vector.objects.create(x=2.0, y=4.0)
>>> vector = Vector.objects.annotate(log=Log('x', 'y')).get()
>>> vector.log
2.0
Mod
- class Mod(expression1, expression2, **extra)
接受两个数值字段或表达式,并返回第一个字段除以第二个字段的余数(模数运算)。
用法示例:
>>> from django.db.models.functions import Mod
>>> Vector.objects.create(x=5.4, y=2.3)
>>> vector = Vector.objects.annotate(mod=Mod('x', 'y')).get()
>>> vector.mod
0.8
Pi
- class Pi(**extra)
返回数学常数 π
的值。
Power
- class Power(expression1, expression2, **extra)
接受两个数值字段或表达式,并将第一个字段的值提高到第二个字段的幂。
用法示例:
>>> from django.db.models.functions import Power
>>> Vector.objects.create(x=2, y=-2)
>>> vector = Vector.objects.annotate(power=Power('x', 'y')).get()
>>> vector.power
0.25
Radians
- class Radians(expression, **extra)
将数值字段或表达式从度数转换为弧度。
用法示例:
>>> from django.db.models.functions import Radians
>>> Vector.objects.create(x=-90, y=180)
>>> vector = Vector.objects.annotate(x_r=Radians('x'), y_r=Radians('y')).get()
>>> vector.x_r, vector.y_r
(-1.5707963267948966, 3.141592653589793)
它也可以注册为转换。 例如:
>>> from django.db.models import FloatField
>>> from django.db.models.functions import Radians
>>> FloatField.register_lookup(Radians)
>>> # Get vectors whose radians are less than 1
>>> vectors = Vector.objects.filter(x__radians__lt=1, y__radians__lt=1)
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)
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)
2.1 版中的新功能。
接受数字字段或表达式,并将表达式的文本表示形式作为单个字符返回。 它的工作原理与 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)
接受至少两个文本字段或表达式的列表并返回连接的文本。 每个参数必须是文本或字符类型。 如果你想连接一个 TextField()
和一个 CharField()
,那么一定要告诉 Django output_field
应该是一个 TextField()
。 在连接 Value
时,也需要指定 output_field
,如下例所示。
此函数永远不会有空结果。 在 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)
2.1 版中的新功能。
返回给定文本字段或表达式的前 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)
接受单个文本字段或表达式并返回该值具有的字符数。 如果表达式为空,则长度也将为空。
用法示例:
>>> # 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)
2.1 版中的新功能。
返回用 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
Ord
- class Ord(expression, **extra)
2.1 版中的新功能。
接受单个文本字段或表达式,并返回该表达式第一个字符的 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)
2.1 版中的新功能。
返回重复 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)
2.1 版中的新功能。
将 expression
中所有出现的 text
替换为 replacement
。 默认替换文本是空字符串。 函数的参数区分大小写。
用法示例:
>>> 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)
2.2 版中的新功能。
接受单个文本字段或表达式,并将该表达式的字符按相反顺序返回。
它也可以注册为一个转换,如 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)
2.1 版中的新功能。
返回给定文本字段或表达式的最后 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
StrIndex
- class StrIndex(string, substring, **extra)
返回与 string
中第一次出现 substring
的 1 索引位置相对应的正整数,如果未找到 substring
,则返回 0。
用法示例:
>>> 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>]>
Substr
- class Substr(expression, pos, length=None, **extra)
从从位置 pos
开始的字段或表达式中返回长度为 length
的子字符串。 该位置为 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)
2.1 版中的新功能。
返回给定的文本字段或表达式的值,并去除前导和尾部的空格。
用法示例:
>>> 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)
计算窗口或分区内某个值的累积分布。 累积分布定义为当前行之前或与之对等的行数除以帧中的总行数。
FirstValue
- class FirstValue(expression, **extra)
返回在窗口框架第一行的行处计算的值,如果不存在这样的值,则返回 None
。
Lag
- class Lag(expression, offset=1, default=None, **extra)
计算偏移offset
的值,如果不存在行,则返回default
。
default
必须与 expression
具有相同的类型,但是,这仅由数据库验证,而不是在 Python 中验证。
Lead
- class Lead(expression, offset=1, default=None, **extra)
计算给定 帧 中的主值。 offset
和 default
都相对于当前行进行评估。
default
必须与 expression
具有相同的类型,但是,这仅由数据库验证,而不是在 Python 中验证。
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)
计算框架子句中行的百分位等级。 此计算等效于评估:
(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 计算无间隙的秩。