django DatabaseFunctions

from django.db.functions import ...

Cast() 转换类型

value = Value.objects.annotate(field_as_float=Cast('integer', FloatField())).get()
print(value.field_as_float)  # 4

Coalesce() 查找第一个不能为空的值

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

Greatest 查询最大值

comments = Comment.objects.annotate(last_updated=Greatest('modified', 'blog__modified'))

Least 查询最小值

Date Functions

week_day:查询日期在一周中的第几天,1代表星期天,2代表星期一,7代表星期六

week:查询日期在一年中的第一周,范围在1-52/53

lookup_name 都是Extract的子类

>>> 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 extracts
class ExtractYear(expression, tzinfo=None, **extra)[source]
	lookup_name = 'year'
class ExtractMonth(expression, tzinfo=None, **extra)[source]
	lookup_name = 'month'
class ExtractDay(expression, tzinfo=None, **extra)[source]
	lookup_name = 'day'
class ExtractWeekDay(expression, tzinfo=None, **extra)[source]
	lookup_name = 'week_day'
class ExtractWeek(expression, tzinfo=None, **extra)[source]
	lookup_name = 'week'
class ExtractQuarter(expression, tzinfo=None, **extra)[source]
	New in Django 2.0:
	lookup_name = 'quarter'

它们在逻辑上等价于Extract('date_field', lookup_name)。每个类也是在DateField和DateTimeField上注册为__(lookup_name)的转换,例如__year。
由于DateFields没有时间组件,所以只有提取处理日期部分的子类才能与DateField一起使用:

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

DateTimeField extracts

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'

它们在逻辑上等价于提取('datetime_field', lookup_name)。每个类也是在DateTimeField注册为__(lookup_name)的转换,例如__minute。

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

当USE_TZ为真时,datetimes将存储在UTC的数据库中。如果Django中激活了不同的时区,则在提取值之前将datetime转换为该时区。下面的示例将转换为墨尔本时区(UTC +10:00),它将更改返回的日、工作日和小时值:

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

第二个方法

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

在执行时返回系统当前时间
>>> from django.db.models.functions import Now
>>> Article.objects.filter(published__lte=Now())

Trunc

日期截断

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

当你只想知道年,小时,或者日 而不需要秒,Trunc函数对于filter和aggregate日期非常有用。例如:您可以使用Trunc计算每天的销售额。

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

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

DateField truncation

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'

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 truncation

class TruncDate(expression, **extra)
	lookup_name = 'date'
	output_field = DateField()

class TruncTime(expression, **extra)
	lookup_name = 'time'
	output_field = TimeField()

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'

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

Chr

类似python chr()函数

concat

接受至少两个文本字段或表达式的列表,并返回连接的文本。每个参数必须是文本或char类型。如果要将TextField()与CharField()连接起来,那么一定要告诉Django output_field应该是TextField()。在连接值时,还需要指定output_field,如下例所示。
这个函数永远不会有空结果。在后端,如果null参数导致整个表达式为null, Django将确保每个null部分首先转换为空字符串。

>>> # Get the display name as "name (goes_by)"# Get the disp 
>>> 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

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

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

它也可以注册到transform

>>> fromfrom  django.db.modelsdjango.db.models  importimport  CharFieldCharField
>>> fromfrom  django.db.models.functionsdjango.db.models.functions  importimport  LengthLength
>>> CharFieldCharField..register_lookupregister_lookup((LengthLength))
>>> # Get authors whose name is longer than 7 characters# Get authors whose name is longer than 7 characters
>>> authorsauthors  ==  AuthorAuthor..objectsobjects..filterfilter((name__length__gtname__length__gt==77))

Lower

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

补充值到所给长度

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

Ord

类似python ord()函数

Repeat

重复值到所给次数

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

替换值,默认替换成empty string

>>> 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'}]>

与Left类似,返回右侧指定长度的字符串

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

与LPad类似

RTrim

与LTrim类似

StrIndex

返回指定字符在字段值中的索引值

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

截断字符串

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

去除字段值左右两边的指定字符

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

转成大写

>>> 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
原文地址:https://www.cnblogs.com/LTEF/p/9736810.html