資料庫函數

以下文件化的類別提供使用者在 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
>>> from django.db.models.functions import Coalesce
>>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
>>> author = Author.objects.annotate(screen_name=Coalesce("alias", "goes_by", "name")).get()
>>> print(author.screen_name)
Maggie

>>> # Prevent an aggregate Sum() from returning None
>>> # The aggregate default argument uses Coalesce() under the hood.
>>> aggregated = Author.objects.aggregate(
...     combined_age=Sum("age"),
...     combined_age_default=Sum("age", default=0),
...     combined_age_coalesce=Coalesce(Sum("age"), 0),
... )
>>> print(aggregated["combined_age"])
None
>>> print(aggregated["combined_age_default"])
0
>>> print(aggregated["combined_age_coalesce"])
0

警告

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

Collate

class Collate(expression, collation)[原始碼]

接受一個表達式和一個定序名稱以進行查詢。

例如,要在 SQLite 中不區分大小寫地篩選

>>> Author.objects.filter(name=Collate(Value("john"), "nocase"))
<QuerySet [<Author: John>, <Author: john>]>

它也可以在排序時使用,例如在 PostgreSQL 中

>>> Author.objects.order_by(Collate("name", "et-x-icu"))
<QuerySet [<Author: Ursula>, <Author: Veronika>, <Author: Ülle>]>

Greatest

class Greatest(*expressions, **extra)[原始碼]

接受至少兩個欄位名稱或表達式的列表,並返回最大值。每個引數都必須是相似的類型,因此混合文字和數字將導致資料庫錯誤。

使用範例

class Blog(models.Model):
    body = models.TextField()
    modified = models.DateTimeField(auto_now=True)


class Comment(models.Model):
    body = models.TextField()
    modified = models.DateTimeField(auto_now=True)
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
>>> from django.db.models.functions import Greatest
>>> blog = Blog.objects.create(body="Greatest is the best.")
>>> comment = Comment.objects.create(body="No, Least is better.", blog=blog)
>>> comments = Comment.objects.annotate(last_updated=Greatest("modified", "blog__modified"))
>>> annotated_comment = comments.get()

annotated_comment.last_updated 將是 blog.modifiedcomment.modified 中最新的。

警告

當一個或多個表達式可能為 null 時,Greatest 的行為在資料庫之間有所不同

  • PostgreSQL: Greatest 將返回最大的非空表達式,如果所有表達式都是 null,則返回 null

  • SQLite、Oracle 和 MySQL:如果任何表達式為 nullGreatest 將返回 null

如果您知道提供為預設值的合理最小值,則可以使用 Coalesce 來模擬 PostgreSQL 的行為。

JSONObject

class JSONObject(**fields)[原始碼]

接受鍵值對的列表,並返回包含這些鍵值對的 JSON 物件。

使用範例

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

Least

class Least(*expressions, **extra)[原始碼]

接受至少兩個欄位名稱或表達式的列表,並返回最小值。每個引數都必須是相似的類型,因此混合文字和數字將導致資料庫錯誤。

警告

當一個或多個表達式可能為 null 時,Least 的行為在資料庫之間有所不同

  • PostgreSQL: Least 將返回最小的非空表達式,如果所有表達式都是 null,則返回 null

  • SQLite、Oracle 和 MySQL:如果任何表達式為 nullLeast 將返回 null

如果您知道提供為預設值的合理最大值,則可以使用 Coalesce 來模擬 PostgreSQL 的行為。

NullIf

class NullIf(expression1, expression2)[原始碼]

接受兩個表達式,如果它們相等則返回 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)[原始碼]

以數字形式提取日期的組成部分。

接受一個代表 DateFieldDateTimeFieldTimeFieldDurationFieldexpression,以及一個 lookup_name,並以 IntegerField 的形式回傳 lookup_name 所參照的日期部分。Django 通常使用資料庫的 extract 函數,因此您可以使用資料庫支援的任何 lookup_name。可以傳遞 zoneinfo 通常提供的 tzinfo 子類別,以提取特定時區的值。

給定日期時間 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
2

week

week lookup_type 是根據 ISO-8601 計算的,亦即一週從星期一開始。一年的第一週是包含該年第一個星期四的那一週,也就是說,第一週的大部分(四天或以上)日子都在該年。回傳的值範圍為 1 到 52 或 53。

上面的每個 lookup_name 都有一個對應的 Extract 子類別(如下所列),通常應該使用這些子類別,而不是更冗長的等效寫法,例如,使用 ExtractYear(...) 而不是 Extract(..., lookup_name='year')

使用範例

>>> from datetime import datetime
>>> from django.db.models.functions import Extract
>>> start = datetime(2015, 6, 15)
>>> end = datetime(2015, 7, 2)
>>> Experiment.objects.create(
...     start_datetime=start, start_date=start.date(), end_datetime=end, end_date=end.date()
... )
>>> # Add the experiment start year as a field in the QuerySet.
>>> experiment = Experiment.objects.annotate(
...     start_year=Extract("start_datetime", "year")
... ).get()
>>> experiment.start_year
2015
>>> # How many experiments completed in the same year in which they started?
>>> Experiment.objects.filter(start_datetime__year=Extract("end_datetime", "year")).count()
1

DateField 提取

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

回傳 ISO-8601 週數年份。

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

回傳 ISO-8601 星期幾,其中星期一為第 1 天,星期日為第 7 天。

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

這些在邏輯上等同於 Extract('date_field', lookup_name)。每個類別也是在 DateFieldDateTimeField 上註冊為 __(lookup_name)Transform,例如 __year

由於 DateField 沒有時間元件,因此只有處理日期部分的 Extract 子類別才能與 DateField 一起使用。

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

DateTimeField 提取

除了以下項目外,上面列出的 DateField 的所有提取也可用於 DateTimeField

class ExtractHour(expression, tzinfo=None, **extra)[原始碼]
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, 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_TZTrue 時,日期時間會以 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}

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

Oracle

在 Oracle 上,使用 SQL LOCALTIMESTAMP 來避免將 CURRENT_TIMESTAMP 轉換為 DateTimeField 時的問題。

在 Django 5.0 中變更

在較舊的版本中,在 Oracle 上使用 SQL CURRENT_TIMESTAMP,而不是 LOCALTIMESTAMP

Trunc

class Trunc(expression, kind, output_field=None, tzinfo=None, **extra)[原始碼]

將日期截斷至某個重要的元件。

當您只關心某件事是否發生在特定的年份、小時或日期,而不是確切的秒數時,Trunc(及其子類別)可用於篩選或彙總您的資料。例如,您可以使用 Trunc 來計算每天的銷售量。

Trunc 接受單一的 expression,表示 DateFieldTimeFieldDateTimeField,一個表示日期或時間部分的 kind,以及一個 output_field,其為 DateTimeField()TimeField()DateField()。它會傳回日期時間、日期或時間,具體取決於 output_field,其中直到 kind 的欄位設定為其最小值。如果省略 output_field,它將預設為 expressionoutput_field。可以傳遞通常由 zoneinfo 提供的 tzinfo 子類別,以在特定時區中截斷值。

給定日期時間 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)[原始碼]
kind = 'year'
class TruncMonth(expression, output_field=None, tzinfo=None, **extra)[原始碼]
kind = 'month'
class TruncWeek(expression, output_field=None, tzinfo=None, **extra)[原始碼]

截斷到該週的星期一午夜。

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

這些在邏輯上等同於 Trunc('date_field', kind)。它們會截斷日期中所有直到 kind 的部分,允許以較低的精度對日期進行分組或篩選。expression 可以具有 DateFieldDateTimeFieldoutput_field

由於 DateField 沒有時間組件,因此只有處理日期部分的 Trunc 子類別才能與 DateField 一起使用。

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

>>> import zoneinfo
>>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
>>> experiments_per_month = (
...     Experiment.objects.annotate(month=TruncMonth("start_datetime", tzinfo=melb))
...     .values("month")
...     .annotate(experiments=Count("id"))
... )
>>> for exp in experiments_per_month:
...     print(exp["month"], exp["experiments"])
...
2015-06-01 00:00:00+10:00 1
2016-01-01 00:00:00+11:00 1
2014-06-01 00:00:00+10:00 1

DateTimeField 截斷

class TruncDate(expression, tzinfo=None, **extra)[原始碼]
lookup_name = 'date'
output_field = DateField()

TruncDate 會將 expression 轉換為日期,而不是使用內建的 SQL 截斷函數。它也註冊為 DateTimeField 的轉換,名稱為 __date

class TruncTime(expression, tzinfo=None, **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 必須具有 DateTimeFieldoutput_field

使用範例

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

TimeField 截斷

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 可以具有 TimeFieldDateTimeFieldoutput_field

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

數學函數

我們將在數學函數範例中使用以下模型

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)

Random

class Random(**extra)[原始碼]

傳回範圍在 0.0 x < 1.0 之間的隨機值。

Round

class Round(expression, precision=0, **extra)[原始碼]

將數值欄位或運算式四捨五入到 precision (必須為整數)小數位數。預設情況下,它會四捨五入到最接近的整數。半數值是向上還是向下捨入取決於資料庫。

使用範例

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

它也可以註冊為轉換。例如

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

Sign

class Sign(expression, **extra)[原始碼]

傳回數值欄位或運算式的符號(-1、0、1)。

使用範例

>>> from django.db.models.functions import Sign
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_sign=Sign("x"), y_sign=Sign("y")).get()
>>> vector.x_sign, vector.y_sign
(1, -1)

它也可以註冊為轉換。例如

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Sign
>>> FloatField.register_lookup(Sign)
>>> # Get vectors whose signs of components are less than 0.
>>> vectors = Vector.objects.filter(x__sign__lt=0, y__sign__lt=0)

Sin

class Sin(expression, **extra)[原始碼]

傳回數值欄位或運算式的正弦值。

使用範例

>>> from django.db.models.functions import Sin
>>> Vector.objects.create(x=5.4, y=-2.3)
>>> vector = Vector.objects.annotate(x_sin=Sin("x"), y_sin=Sin("y")).get()
>>> vector.x_sin, vector.y_sin
(-0.7727644875559871, -0.7457052121767203)

它也可以註冊為轉換。例如

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Sin
>>> FloatField.register_lookup(Sin)
>>> # Get vectors whose sin() is less than 0
>>> vectors = Vector.objects.filter(x__sin__lt=0, y__sin__lt=0)

Sqrt

class Sqrt(expression, **extra)[原始碼]

傳回非負數值欄位或運算式的平方根。

使用範例

>>> from django.db.models.functions import Sqrt
>>> Vector.objects.create(x=4.0, y=12.0)
>>> vector = Vector.objects.annotate(x_sqrt=Sqrt("x"), y_sqrt=Sqrt("y")).get()
>>> vector.x_sqrt, vector.y_sqrt
(2.0, 3.46410)

它也可以註冊為轉換。例如

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Sqrt
>>> FloatField.register_lookup(Sqrt)
>>> # Get vectors whose sqrt() is less than 5
>>> vectors = Vector.objects.filter(x__sqrt__lt=5, y__sqrt__lt=5)

Tan

class Tan(expression, **extra)[原始碼]

傳回數值欄位或運算式的正切值。

使用範例

>>> from django.db.models.functions import Tan
>>> Vector.objects.create(x=0, y=12)
>>> vector = Vector.objects.annotate(x_tan=Tan("x"), y_tan=Tan("y")).get()
>>> vector.x_tan, vector.y_tan
(0.0, -0.6358599286615808)

它也可以註冊為轉換。例如

>>> from django.db.models import FloatField
>>> from django.db.models.functions import Tan
>>> FloatField.register_lookup(Tan)
>>> # Get vectors whose tangent is less than 0
>>> vectors = Vector.objects.filter(x__tan__lt=0, y__tan__lt=0)

文字函式

Chr

class Chr(expression, **extra)[原始碼]

接受數值欄位或運算式,並將運算式的文字表示形式傳回為單一字元。它的運作方式與 Python 的 chr() 函式相同。

Length 類似,它可以註冊為 IntegerField 的轉換。預設的查詢名稱是 chr

使用範例

>>> from django.db.models.functions import Chr
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.filter(name__startswith=Chr(ord("M"))).get()
>>> print(author.name)
Margaret Smith

Concat

class Concat(*expressions, **extra)[原始碼]

接受至少兩個文字欄位或運算式的列表,並傳回串連的文字。每個引數都必須是文字或字元類型。如果您想將 TextField()CharField() 串連,請務必告訴 Django output_field 應該是 TextField()。在串連 Value 時,如下面的範例所示,也必須指定 output_field

此函式永遠不會產生 null 結果。在 null 引數導致整個運算式為 null 的後端,Django 會確保每個 null 部分都先轉換為空字串。

使用範例

>>> # Get the display name as "name (goes_by)"
>>> from django.db.models import CharField, Value as V
>>> from django.db.models.functions import Concat
>>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
>>> author = Author.objects.annotate(
...     screen_name=Concat("name", V(" ("), "goes_by", V(")"), output_field=CharField())
... ).get()
>>> print(author.screen_name)
Margaret Smith (Maggie)

Left

class Left(expression, length, **extra)[原始碼]

傳回給定文字欄位或運算式的前 length 個字元。

使用範例

>>> from django.db.models.functions import Left
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(first_initial=Left("name", 1)).get()
>>> print(author.first_initial)
M

Length

class Length(expression, **extra)[原始碼]

接受單一文字欄位或運算式,並傳回值具有的字元數。如果運算式為 null,則長度也會為 null。

使用範例

>>> # Get the length of the name and goes_by fields
>>> from django.db.models.functions import Length
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(
...     name_length=Length("name"), goes_by_length=Length("goes_by")
... ).get()
>>> print(author.name_length, author.goes_by_length)
(14, None)

它也可以註冊為轉換。例如

>>> from django.db.models import CharField
>>> from django.db.models.functions import Length
>>> CharField.register_lookup(Length)
>>> # Get authors whose name is longer than 7 characters
>>> authors = Author.objects.filter(name__length__gt=7)

Lower

class Lower(expression, **extra)[原始碼]

接受單一文字欄位或運算式,並傳回小寫表示形式。

它也可以註冊為轉換,如 Length 中所述。

使用範例

>>> from django.db.models.functions import Lower
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_lower=Lower("name")).get()
>>> print(author.name_lower)
margaret smith

LPad

class LPad(expression, length, fill_text=Value(' '), **extra)[原始碼]

傳回給定文字欄位或運算式的值,並在左側以 fill_text 填補,使結果值為 length 個字元長。預設的 fill_text 是空格。

使用範例

>>> from django.db.models import Value
>>> from django.db.models.functions import LPad
>>> Author.objects.create(name="John", alias="j")
>>> Author.objects.update(name=LPad("name", 8, Value("abc")))
1
>>> print(Author.objects.get(alias="j").name)
abcaJohn

LTrim

class LTrim(expression, **extra)[原始碼]

Trim 類似,但僅刪除開頭的空格。

MD5

class MD5(expression, **extra)[原始碼]

接受單一文字欄位或運算式,並傳回字串的 MD5 雜湊值。

它也可以註冊為轉換,如 Length 中所述。

使用範例

>>> from django.db.models.functions import MD5
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_md5=MD5("name")).get()
>>> print(author.name_md5)
749fb689816b2db85f5b169c2055b247

Ord

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

接受單一文字欄位或表達式,並傳回該表達式第一個字元的 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)[source]

傳回給定文字欄位或表達式重複 number 次的值。

使用範例

>>> from django.db.models.functions import Repeat
>>> Author.objects.create(name="John", alias="j")
>>> Author.objects.update(name=Repeat("name", 3))
1
>>> print(Author.objects.get(alias="j").name)
JohnJohnJohn

Replace

class Replace(expression, text, replacement=Value(''), **extra)[source]

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

接受單一文字欄位或表達式,並傳回該表達式中字元的反向順序。

它也可以註冊為轉換,如 Length 中所述。預設的查詢名稱為 reverse

使用範例

>>> from django.db.models.functions import Reverse
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(backward=Reverse("name")).get()
>>> print(author.backward)
htimS teragraM

Right

class Right(expression, length, **extra)[source]

傳回給定文字欄位或表達式的最後 length 個字元。

使用範例

>>> from django.db.models.functions import Right
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(last_letter=Right("name", 1)).get()
>>> print(author.last_letter)
h

RPad

class RPad(expression, length, fill_text=Value(' '), **extra)[source]

類似於 LPad,但在右側填充。

RTrim

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

類似於 Trim,但僅移除尾隨空格。

SHA1SHA224SHA256SHA384SHA512

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

接受單一文字欄位或表達式,並傳回字串的特定雜湊值。

它們也可以註冊為轉換,如 Length 中所述。

使用範例

>>> from django.db.models.functions import SHA1
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_sha1=SHA1("name")).get()
>>> print(author.name_sha1)
b87efd8a6c991c390be5a68e8a7945a7851c7e5c

PostgreSQL

必須安裝 pgcrypto 擴充功能。您可以使用 CryptoExtension 遷移操作來安裝它。

Oracle

Oracle 不支援 SHA224 函數。

StrIndex

class StrIndex(string, substring, **extra)[source]

傳回與 substringstring 內第一次出現的 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>]>

警告

在 MySQL 中,資料庫表格的排序規則決定字串比較(例如此函數的 expressionsubstring)是否區分大小寫。預設情況下,比較不區分大小寫。

Substr

class Substr(expression, pos, length=None, **extra)[原始碼]

從欄位或表達式中傳回一個從位置 pos 開始,長度為 length 的子字串。位置是以 1 為起始的索引,因此位置必須大於 0。如果 lengthNone,則會傳回字串的剩餘部分。

使用範例

>>> # Set the alias to the first 5 characters of the name as lowercase
>>> from django.db.models.functions import Lower, Substr
>>> Author.objects.create(name="Margaret Smith")
>>> Author.objects.update(alias=Lower(Substr("name", 1, 5)))
1
>>> print(Author.objects.get(name="Margaret Smith").alias)
marga

Trim

class Trim(expression, **extra)[原始碼]

傳回指定文字欄位或表達式的值,並移除前導和尾隨空格。

使用範例

>>> from django.db.models.functions import Trim
>>> Author.objects.create(name="  John  ", alias="j")
>>> Author.objects.update(name=Trim("name"))
1
>>> print(Author.objects.get(alias="j").name)
John

Upper

class Upper(expression, **extra)[原始碼]

接受單個文字欄位或表達式,並傳回大寫表示形式。

它也可以註冊為轉換,如 Length 中所述。

使用範例

>>> from django.db.models.functions import Upper
>>> Author.objects.create(name="Margaret Smith")
>>> author = Author.objects.annotate(name_upper=Upper("name")).get()
>>> print(author.name_upper)
MARGARET SMITH

視窗函數

有一些函數可以用於 Window 表達式中,計算元素的排名或某些列的 Ntile

CumeDist

class CumeDist(*expressions, **extra)[原始碼]

計算視窗或分割區內值的累積分布。累積分布定義為當前列之前或與當前列對等的列數除以框架中的總列數。

DenseRank

class DenseRank(*expressions, **extra)[原始碼]

等同於 Rank,但不具有間隙。

FirstValue

class FirstValue(expression, **extra)[原始碼]

傳回在視窗框架的第一列評估的值,如果不存在這樣的值,則傳回 None

Lag

class Lag(expression, offset=1, default=None, **extra)[原始碼]

計算偏移量為 offset 的值,如果該處不存在列,則傳回 default

default 的類型必須與 expression 相同,但是,這僅由資料庫驗證,而不是在 Python 中驗證。

MariaDB 和 default

MariaDB 不支援 default 參數。

LastValue

class LastValue(expression, **extra)[原始碼]

FirstValue 類似,它計算給定框架子句中的最後一個值。

Lead

class Lead(expression, offset=1, default=None, **extra)[原始碼]

計算給定 框架 中的前導值。 offsetdefault 都是相對於當前列進行評估。

default 的類型必須與 expression 相同,但是,這僅由資料庫驗證,而不是在 Python 中驗證。

MariaDB 和 default

MariaDB 不支援 default 參數。

NthValue

class NthValue(expression, nth=1, **extra)[原始碼]

計算視窗內相對於偏移量 nth (必須為正值) 的列。如果不存在列,則傳回 None

某些資料庫可能會以不同的方式處理不存在的第 n 個值。例如,對於基於字元的表達式,Oracle 會傳回空字串而不是 None。在這些情況下,Django 不會進行任何轉換。

Ntile

class Ntile(num_buckets=1, **extra)[原始碼]

計算框架子句中每一列的分割,將數字盡可能均勻地分配在 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 計算不帶間隙的排名。

RowNumber

class RowNumber(*expressions, **extra)[原始碼]

根據框架子句的排序或整個查詢的排序(如果沒有對視窗框架進行分割),計算列號。

回到頂部