添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

数据库函数

下面记录的类为用户提供了一种方法,可以在 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=TrueCharField,因为这允许字段有两个 Coalesce,但它对下面的 Coalesce 例子很重要。

比较和转换函数

Cast

class Cast(expression, output_field)[source]

强制 expression 的结果类型为 output_field 的类型。

用法示例:

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

接受至少两个字段名或表达式的列表,并返回第一个非空值(注意,空字符串不被视为空值)。每个参数必须是同样的类型,因此混合文本和数字将导致数据库错误。

使用示例:

>>> # Get a screen name from least to most public
>>> from django.db.models import Sum
>>> from django.db.models.functions import Coalesce
>>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
>>> author = Author.objects.annotate(screen_name=Coalesce("alias", "goes_by", "name")).get()
>>> print(author.screen_name)
Maggie
>>> # Prevent an aggregate Sum() from returning None
>>> # The aggregate default argument uses Coalesce() under the hood.
>>> aggregated = Author.objects.aggregate(
...     combined_age=Sum("age"),
...     combined_age_default=Sum("age", default=0),
...     combined_age_coalesce=Coalesce(Sum("age"), 0),
... )
>>> print(aggregated["combined_age"])
>>> print(aggregated["combined_age_default"])
>>> print(aggregated["combined_age_coalesce"])

Warning

在 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()))

接受一个表达式和一个排序规则名称来进行查询。

例如,在 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>]>

接受至少两个字段名或表达式的列表,并返回最大的值。每个参数必须是同样的类型,所以混合文本和数字会导致数据库错误。

使用实例:

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.modifiedcomment.modified 中最近的。

Warning

当一个或多个表达式可能为 null 时,Greatest 的行为在不同的数据库之间有所不同。

  • PostgreSQL:Greatest 将返回最大的非空表达式,如果所有表达式都是 null,则返回 null

  • SQLite、Oracle 和 MySQL。如果任何表达式是 nullGreatest 将返回 null

  • 如果你知道一个合理的最小值作为默认值,可以使用 Coalesce 来模拟 PostgreSQL 的行为。

    JSONObject

    class JSONObject(**fields)[source]

    接受一组键值对,并返回一个包含这些键值对的 JSON 对象。

    用法示例:

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

    当一个或多个表达式可能是 null 时,Least 的行为在不同的数据库之间有所不同。

  • PostgreSQL:Least 将返回最小的非空表达式,如果所有表达式都是 null,则返回 null

  • SQLite、Oracle 和 MySQL。如果任何表达式是 nullLeast 将返回 null

  • 如果你知道一个合理的最大值作为默认值,可以使用 Coalesce 来模拟 PostgreSQL 的行为。

    NullIf

    class NullIf(expression1, expression2)[source]

    接受两个表达式,如果相等则返回 None,否则返回 expression1

    关于 Oracle 的注意事项

    由于 Oracle 惯例,当表达式为 CharField 类型时,该函数返回空字符串而不是 None

    在 Oracle 上禁止将 Value(None) 传递给 expression1,因为 Oracle 不接受 NULL 作为第一个参数。

    我们将在每个函数的例子中使用以下模型:

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

    Extract

    class Extract(expression, lookup_name=None, tzinfo=None, **extra)[source]

    提取日期的一个组成部分作为一个数字。

    接受表示 DateFieldDateTimeFieldTimeFieldDurationFieldexpression,以及一个 lookup_name,并将被 lookup_name 引用的日期部分作为 IntegerField 返回。Django 通常使用数据库的 extract 函数,因此您可以使用数据库支持的任何 lookup_name。可以传递一个 tzinfo 子类,通常由 zoneinfo 提供,以在特定时区中提取值。

    给定日期时间 2015-06-15 23:30:01.000321+00:00,内置的 lookup_name 返回。

  • "year": 2015

  • "iso_year": 2015

  • "quarter": 2

  • "month": 6

  • "day": 15

  • "week": 25

  • "week_day": 2

  • "iso_week_day": 1

  • "hour": 23

  • "minute": 30

  • "second": 1

  • 如果在 Django 中使用了不同的时区,比如 Australia/Melbourne ,那么在提取值之前,日期时间会被转换为该时区。在上面的例子中,墨尔本的时区偏移是 +10:00。当这个时区被激活时,返回的值将与上述相同,除了:

  • "day": 16

  • "week_day": 3

  • "iso_week_day": 2

  • "hour": 9

  • week_day

    week_day lookup_type 的计算方式与大多数数据库和 Python 的标准函数不同。这个函数将返回星期日的 1,星期一的 2,到星期六的 7

    在 Python 中的等效计算是:

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

    week

    The week lookup_type is calculated based on ISO-8601, i.e., a week starts on a Monday. The first week of a year is the one that contains the year's first Thursday, i.e. the first week has the majority (four or more) of its days in the year. The value returned is in the range 1 to 52 or 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
    >>> # How many experiments completed in the same year in which they started?
    >>> Experiment.objects.filter(start_datetime__year=Extract("end_datetime", "year")).count()
    

    DateField 提取

    class ExtractYear(expression, tzinfo=None, **extra)[source] lookup_name = 'year' class ExtractIsoYear(expression, tzinfo=None, **extra)[source]

    返回 ISO-8601 的周号年份。

    lookup_name = 'iso_year' class ExtractIsoWeekDay(expression, tzinfo=None, **extra)[source]

    返回 ISO-8601 的星期日,第 1 天是星期一,第 7 天是星期天。

    lookup_name = 'iso_week_day'

    这些类在逻辑上等同于 Extract('date_field', lookup_name)。每个类也是一个 TransformDateFieldDateTimeField 上注册为 __(lookup_name)`,例如 __year

    由于 DateField 不包含时间组件,因此只能使用处理日期部分的 Extract 子类与 DateField 一起使用:

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

    这些类在逻辑上等同于 Extract('datetime_field', lookup_name)。每个类也是一个 TransformDateTimeField 上注册为 __(lookup_name),例如 __minute

    DateTimeField 例子:

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

    USE_TZ 设置为 True 时,日期时间将以 UTC 格式存储在数据库中。如果 Django 中有不同的时区激活,那么在提取值之前,日期时间将被转换为该时区。下面的示例将日期时间转换为墨尔本时区(UTC +10:00),这将改变返回的日期、工作日和小时值:

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

    显式传递时区给 Extract 函数的行为与上述相同,并优先于激活的时区:

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

    返回数据库服务器执行查询时的当前日期和时间,通常使用 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 代替。因此为了跨数据库的兼容性,Now() 使用 STATEMENT_TIMESTAMP 代替。如果需要事务时间戳,可以使用 django.contrib.postgres.function.TransactionNow

    Oracle

    在 Oracle 中,使用 SQL LOCALTIMESTAMP 以避免将 CURRENT_TIMESTAMP 强制转换为 DateTimeField 时出现问题。

    Changed in Django 5.0:

    在旧版本中,Oracle 使用 SQL 中的 CURRENT_TIMESTAMP 而不是 LOCALTIMESTAMP

    Trunc

    class Trunc(expression, kind, output_field=None, tzinfo=None, **extra)[source]

    将一个日期截断到一个重要的部分。

    当你只关心某事是否发生在某年、某小时或某天,而不关心确切的秒数时,那么 Trunc (及其子类)可以用来过滤或汇总你的数据。例如,你可以使用 Trunc 来计算每天的销售数量。

    Trunc 接受一个表示 DateFieldTimeFieldDateTimeFieldexpression,一个表示日期或时间部分的 kind,以及一个 output_field,可以是 DateTimeField()TimeField()DateField()。它根据 output_field 返回一个日期时间、日期或时间,其中字段最多到 kind 设置为其最小值。如果省略了 output_field,它将默认为 expressionoutput_field。可以传递一个 tzinfo 子类,通常由 zoneinfo 提供,以在特定时区中截断值。

    给定日期时间 2015-06-15 14:30:50.000321+00:00,内置 kind 返回:

  • "year": 2015-01-01 00:00:00+00:00

  • "quarter": 2015-04-01 00:00:00+00:00

  • "month": 2015-06-01 00:00:00+00:00

  • "week": 2015-06-15 00:00:00+00:00

  • "day": 2015-06-15 00:00:00+00:00

  • "hour": 2015-06-15 14:00:00+00:00

  • "minute": 2015-06-15 14:30:00+00:00

  • "second": 2015-06-15 14:30:50+00:00

  • 如果在 Django 中使用了不同的时区,比如 Australia/Melbourne,那么日期时间会在被截断之前转换为新的时区。在上面的例子中,墨尔本的时区偏移是 +10:00。当这个时区被激活时,返回的值将是:

  • "year": 2015-01-01 00:00:00+11:00

  • "quarter": 2015-04-01 00:00:00+10:00

  • "month": 2015-06-01 00:00:00+10:00

  • "week": 2015-06-16 00:00:00+10:00

  • "day": 2015-06-16 00:00:00+10:00

  • "hour": 2015-06-16 00:00:00+10:00

  • "minute": 2015-06-16 00:30:00+10:00

  • "second": 2015-06-16 00:30:50+10:00

  • 年的偏移量为 +11:00,因为结果过渡到夏令时。

    以上每个 kind 都有一个对应的 Trunc 子类(下面列出的),通常应该用这个子类来代替比较啰嗦的等价物,例如使用 TruncYear(...) 而不是 Trunc(...,kind='year')

    子类都被定义为变换,但它们没有注册任何字段,因为查找名称已经被 Extract 子类保留。

    用法示例:

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

    DateField 截断

    class TruncYear(expression, output_field=None , tzinfo=None, **extra)[source] kind = 'year' class TruncMonth(expression, output_field=None, tzinfo=None, **extra)[source] kind = 'month' class TruncWeek(expression, output_field=None, tzinfo=None, **extra)[source]

    截断到每周一的午夜。

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

    这些在逻辑上等同于 Trunc('date_field', kind)。它们截断日期的所有部分,直至 kind,允许以较低的精度对日期进行分组或过滤。expression 可以有一个 output_fieldDateFieldDateTimeField

    由于 DateField 不包含时间组件,因此只能使用处理日期部分的 Trunc 子类与 DateField 一起使用:

    >>> from datetime import datetime, timezone
    >>> from django.db.models import Count
    >>> from django.db.models.functions import TruncMonth, TruncYear
    >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
    >>> start2 = datetime(2015, 6, 15, 14, 40, 2, 123, tzinfo=timezone.utc)
    >>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=timezone.utc)
    >>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
    >>> Experiment.objects.create(start_datetime=start2, start_date=start2.date())
    >>> Experiment.objects.create(start_datetime=start3, start_date=start3.date())
    >>> experiments_per_year = (
    ...     Experiment.objects.annotate(year=TruncYear("start_date"))
    ...     .values("year")
    ...     .annotate(experiments=Count("id"))
    ... )
    >>> for exp in experiments_per_year:
    ...     print(exp["year"], exp["experiments"])
    2014-01-01 1
    2015-01-01 2
    >>> import zoneinfo
    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
    >>> experiments_per_month = (
    ...     Experiment.objects.annotate(month=TruncMonth("start_datetime", tzinfo=melb))
    ...     .values("month")
    ...     .annotate(experiments=Count("id"))
    ... )
    >>> for exp in experiments_per_month:
    ...     print(exp["month"], exp["experiments"])
    2015-06-01 00:00:00+10:00 1
    2016-01-01 00:00:00+11:00 1
    2014-06-01 00:00:00+10:00 1
    

    TruncDateexpression 投射到一个日期,而不是使用内置的 SQL truncate 函数。在 DateTimeField 上,它也被注册为 __date 的转换。

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

    TruncTimeexpression 投射到一个时间,而不是使用内置的 SQL truncate 函数。在 DateTimeField 上,它也被注册为 __time 的转换。

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

    这些在逻辑上等同于 Trunc('datetime_field', kind)。它们截断日期的所有部分,直至 kind,并允许以较低的精度对日期时间进行分组或过滤。expression 必须有一个 output_fieldDateTimeField

    用法示例:

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

    由于 TimeField 不包含日期组件,因此只能使用处理时间部分的 Trunc 子类与 TimeField 一起使用:

    >>> from datetime import datetime, timezone
    >>> from django.db.models import Count, TimeField
    >>> from django.db.models.functions import TruncHour
    >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
    >>> start2 = datetime(2014, 6, 15, 14, 40, 2, 123, tzinfo=timezone.utc)
    >>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=timezone.utc)
    >>> Experiment.objects.create(start_datetime=start1, start_time=start1.time())
    >>> Experiment.objects.create(start_datetime=start2, start_time=start2.time())
    >>> Experiment.objects.create(start_datetime=start3, start_time=start3.time())
    >>> experiments_per_hour = (
    ...     Experiment.objects.annotate(
    ...         hour=TruncHour("start_datetime", output_field=TimeField()),
    ...     )
    ...     .values("hour")
    ...     .annotate(experiments=Count("id"))
    ... )
    >>> for exp in experiments_per_hour:
    ...     print(exp["hour"], exp["experiments"])
    14:00:00 2
    17:00:00 1
    >>> import zoneinfo
    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
    >>> experiments_per_hour = (
    ...     Experiment.objects.annotate(
    ...         hour=TruncHour("start_datetime", tzinfo=melb),
    ...     )
    ...     .values("hour")
    ...     .annotate(experiments=Count("id"))
    ... )
    >>> for exp in
    
    
    
    
        
     experiments_per_hour:
    ...     print(exp["hour"], exp["experiments"])
    2014-06-16 00:00:00+10:00 2
    2016-01-01 04:00:00+11:00 1
    

    用法示例:

    >>> 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)
    

    返回一个数值字段或表达式的余弦值。表达式的值必须在 -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)
    

    返回一个数值字段或表达式的正弦值。表达式的值必须在 -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)
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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
    

    用法示例:

    >>> 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
    

    用法示例:

    >>> 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
    

    用法示例:

    >>> 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)
    

    将数值字段或表达式四舍五入到指定的小数位数 precision (必须为整数)。默认情况下,它会四舍五入到最接近的整数。半数值是向上还是向下舍入取决于数据库。

    用法示例:

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

    它也可以注册为一个转换操作。例如:

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

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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)
    

    用法示例:

    >>> 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)
    

    接受一个数值字段或表达式,并将表达式的文本表示形式作为单个字符返回。它的工作原理与 Python 的 chr() 函数相同。

    Length 一样,它也可以在 IntegerField 上作为变换注册。默认的查询名是 chr

    用法示例: