Django数据库函数使用
Django数据库函数使用
通用方法
from django.db.models.functions import Cast, Coalesce, Concat, ConcatPair, Greatest
# Cast,类型转换
q1 = TradeDetail.objects.values("profit", "name").annotate( profit=F("money") * F(Cast('direction', FloatField())))
# Coalesce,从前向后,查询第一个不为空的值
q2 = TradeDetail.objects.annotate(c=Coalesce('name', 'money'))
# Concat拼接
TradeDetail.objects.update(name=Concat('name', 'money'))
# ConcatPair,拼接(仅两个参数)
qs = UserInfo.objects.annotate(new_name=ConcatPair('name', 'addr', 'school'))
for i in qs: # addr是- school是*
print(i.new_name) # lqz-*
# Greatest, 获取比较大的值; least获取比较小的值
TradeDetail.objects.annotate(c=Greatest('id', 'money',output_field=FloatField()))
# Length获取长度
qs = UserInfo.objects.annotate(new=Length('name')).values('new')
# {'new': 3}
# Lower,Upper,变大小写
TradeDetail.objects.annotate(c=Lower('name'))
TradeDetail.objects.annotate(c=Upper('name'))
# Now。获取当前时间
TradeDetail.objects.annotate(c=Now())
# Left 获取字段的指定字符长度的值
qs = UserInfo.objects.annotate(new_name=Left('name', 2)).values('new_name')
# {'new_name': 'lq'}
Extract
提取日期的一个组成部分作为一个数字。
取一个代表 DateField
、DateTimeField
、TimeField
或 DurationField
和 lookup_name
的 expression
和一个 lookup_name
引用的日期部分作为 IntegerField
返回。Django 通常使用数据库的 extract 函数,所以你可以使用任何数据库支持的 lookup_name
。tzinfo
子类,通常由 pytz
提供,可以通过提取特定时区的值。
给定日期时间 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
qs = UserInfo.objects.annotate(
year=Extract('registered_on', 'year'),
month=Extract('registered_on', 'month'),
day=Extract('registered_on', 'day'),
quarter=Extract('registered_on', 'quarter'),
week=Extract('registered_on', 'week'),
week_day=Extract('registered_on', 'week_day'),
iso_week_day=Extract('registered_on', 'iso_week_day'),
).values('year', 'month', 'day', 'quarter', 'week', 'week_day', 'iso_week_day')
for i in qs:
print(i)
{'year': 2023, 'month': 1, 'day': 2, 'quarter': 1, 'week': 1, 'week_day': 2, 'iso_week_day': 1}
{'year': 2023, 'month': 1, 'day': 11, 'quarter': 1, 'week': 2, 'week_day': 4, 'iso_week_day': 3}
{'year': 2021, 'month': 7, 'day': 12, 'quarter': 3, 'week': 28, 'week_day': 2, 'iso_week_day': 1}
{'year': 2022, 'month': 1, 'day': 2, 'quarter': 1, 'week': 52, 'week_day': 1, 'iso_week_day': 7}
{'year': 2023, 'month': 1, 'day': 9, 'quarter': 1, 'week': 2, 'week_day': 2, 'iso_week_day': 1}
{'year': 2020, 'month': 1, 'day': 1, 'quarter': 1, 'week': 1, 'week_day': 4, 'iso_week_day': 3}
{'year': 2022, 'month': 12, 'day': 7, 'quarter': 4, 'week': 49, 'week_day': 4, 'iso_week_day': 3}
上面的每个 lookup_name
都有一个相应的 Extract
子类(下面列出的),通常应该用这个子类来代替比较啰嗦的等价物,例如,使用 ExtractYear(...)
而不是 Extract(...,lookup_name='year')
。
Trunc
将一个日期截断到一个重要的部分。
当你只关心某事是否发生在某年、某小时或某天,而不关心确切的秒数时,那么 Trunc
(及其子类)可以用来过滤或汇总你的数据。例如,你可以使用 Trunc
来计算每天的销售数量。
给定日期时间 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')
。
qs = UserInfo.objects.annotate(
init_year=Trunc('registered_on', 'year'),
init_month=Trunc('registered_on', 'month'),
init_day=Trunc('registered_on', 'day'),
init_quarter=Trunc('registered_on', 'quarter'),
init_week=Trunc('registered_on', 'week'),
).values('init_year', 'init_month', 'init_day', 'init_quarter', 'init_week')
for i in qs:
print(i)
{'init_year': datetime.date(2023, 1, 1), 'init_month': datetime.date(2023, 1, 1), 'init_day': datetime.date(2023, 1, 2), 'init_quarter': datetime.date(2023, 1, 1), 'init_week': datetime.date(2023, 1, 2)}
{'init_year': datetime.date(2023, 1, 1), 'init_month': datetime.date(2023, 1, 1), 'init_day': datetime.date(2023, 1, 11), 'init_quarter': datetime.date(2023, 1, 1), 'init_week': datetime.date(2023, 1, 9)}
{'init_year': datetime.date(2021, 1, 1), 'init_month': datetime.date(2021, 7, 1), 'init_day': datetime.date(2021, 7, 12), 'init_quarter': datetime.date(2021, 7, 1), 'init_week': datetime.date(2021, 7, 12)}
{'init_year': datetime.date(2022, 1, 1), 'init_month': datetime.date(2022, 1, 1), 'init_day': datetime.date(2022, 1, 2), 'init_quarter': datetime.date(2022, 1, 1), 'init_week': datetime.date(2021, 12, 27)}
{'init_year': datetime.date(2023, 1, 1), 'init_month': datetime.date(2023, 1, 1), 'init_day': datetime.date(2023, 1, 9), 'init_quarter': datetime.date(2023, 1, 1), 'init_week': datetime.date(2023, 1, 9)}
{'init_year': datetime.date(2020, 1, 1), 'init_month': datetime.date(2020, 1, 1), 'init_day': datetime.date(2020, 1, 1), 'init_quarter': datetime.date(2020, 1, 1), 'init_week': datetime.date(2019, 12, 30)}
{'init_year': datetime.date(2022, 1, 1), 'init_month': datetime.date(2022, 12, 1), 'init_day': datetime.date(2022, 12, 7), 'init_quarter': datetime.date(2022, 10, 1), 'init_week': datetime.date(2022, 12, 5)}