基于行的日期字段为django queryset添加上一个星期天的注解

zbq4xfa0  于 2021-06-25  发布在  Mysql
关注(0)|答案(1)|浏览(341)

我有一张table和一套餐具 Orders 我的顾客做的。
客户可以选择交货日期。该值存储在每个 Order 在一个叫做 Order.delivery_date (没有太多创造性)

class Order(BaseModel):
    customer = ForeignKey(Customer, on_delete=CASCADE, related_name='orders')
    delivery_date = DateField(null=True, blank=True)

我想注解一个查询集 Orders 和上个星期天一样 delivery_date (主要是创建周报,每周“bucketized”)
我想“哦!我知道!我将得到本周的日期索引,然后减去a datetime.timedelta 使用该周的天数索引,我将使用它来获取星期日(如python的.weekday()函数)“:

from server.models import *
import datetime
from django.db.models import F, DateField, ExpressionWrapper
from django.db.models.functions import ExtractWeekDay

Order.objects.filter(
    delivery_date__isnull=False
).annotate(
    sunday=ExpressionWrapper(
        F('delivery_date') - datetime.timedelta(days=ExtractWeekDay(F('delivery_date')) + 1),
        output_field=DateField()
    )
).last().sunday

但如果我这么做,我会得到一个 TypeError: unsupported type for timedelta days component: CombinedExpression 当尝试“构造”时: timedelta 表情。
不使用 FExtract 也没有什么区别:不管我是否使用 Extract(F('delivery_date')) 或者 Extract('delivery_date') 这是一个python3.4版本,在mysql 5.7.21上使用了django 2.0.3
我知道我总是能拿到钱 Order 对象并在python中执行此操作(我甚至有一个小的helper函数可以执行此操作),但是从db中获取带有该注解的对象(也用于学习目的)会很好
先谢谢你。

bvk5enib

bvk5enib1#

哦,我忘了 extra 看起来应该这样做(至少对mysql是这样)

orders_q = Order.objects.filter(
    delivery_date__isnull=False
).extra(
    select={
        'sunday': "DATE_ADD(`delivery_date`, interval(1 - DAYOFWEEK(`delivery_date`)) DAY)"
    },
).order_by('-id')

似乎有用:

for record in orders_q.values('sunday', 'delivery_date'):
    print("date: {delivery_date}, sunday: {sunday} is_sunday?: {is_sunday}".format(
        is_sunday=record['sunday'].weekday() == 6,**record)
    )
date: 2018-06-04, sunday: 2018-06-03 is_sunday?: True
date: 2018-05-30, sunday: 2018-05-27 is_sunday?: True
date: 2018-05-21, sunday: 2018-05-20 is_sunday?: True
date: 2018-06-04, sunday: 2018-06-03 is_sunday?: True

编辑:显然, extra 即将被否决/不支持。至少,不是很。。。呃。。。深受django开发商的欢迎。也许用这个更好 RawSQL 相反。实际上,我在尝试进一步过滤时遇到了问题 sunday 注解使用 extra 但我不明白 RawSQL 方法。。
这似乎效果更好:

orders_q = orders_q.annotate(
    sunday=RawSQL("DATE_ADD(`delivery_date`, interval(1 - DAYOFWEEK(`delivery_date`)) DAY)", ())
)

这让我可以进一步解释。。。

orders_q.annotate(sunday_count=Count('sunday'))

我不知道为什么,但是当我使用 extra ,我会得到 Cannot resolve keyword 'sunday' into field

相关问题