Django QuerySet日期操作



我有一个模型,其中存储了一个时区日期时间对象。我从网站上向我的一个视图打了一个Ajax电话,它进行了以下呼叫:

def uploads(request):
    user = User.objects.get(username=request.user.get_username())
    cases = Case.objects.filter(user_id=user.pk).order_by('-uploaded_on')[:5]
    return JsonResponse(serializers.serialize('json', cases, fields=('col1', 'col2', 'col3', 'uploaded_on')), safe=False)

当在前端接收到JSON响应时,会使用JS对其进行解析和分析。我想在这里做的是用用户的时区修改"uploaded_on"列(我已经可以用user.timezone访问它,目前显示为字符串,例如"Germany/Berlin",但可以用pytz包轻松地将其转换为必要的对象(。

当我尝试像下面这样迭代QuerySet时,在前端接收到的值不会改变:

for case in cases:
    case.uploaded_on.astimezone(pytz.timezone(user.timezone))

这可能与QuerySet是惰性的这一事实有关,就像Django文档中描述的那样。有人能建议如何做到这一点吗?

还有一个额外的问题:使用Django的序列化程序,我可以在一个JSON响应中传递多个QuerySet吗?当我试图在列表中打包一些时,我会得到一个MultiValueDictKeyError:

return JsonResponse(serializers.serialize('json', [cases, cases2]), safe=False)

对我来说,有两种方法:

  1. 用一个新列(类似于uploaded_at_utz(注释cases查询集,并在数据库级别进行时区操作。例如,您可以使用TruncSecond函数来执行以下操作:

    cases = Case.objects.filter(user_id=user.pk).annotate(uploaded_at_utz=TruncSecond('uploaded_on', tzinfo=pytz.timezone(user.timezone)).order_by('-uploaded_on')[:5]
    
  2. 另一种方法是在python级别执行此操作。为此,我会选择生成器函数,类似于:

    def convert_to_timezone(cases, tzinfo):
        for case in cases:
            case.uploaded_on = case.uploaded_on.astimezone(tzinfo)
            yield case
    

然后,在中将convert_to_timezone(cases, pytz.timezone(user.timezone))传递给JsonResponse构造函数。

您还应该探索timezone.override和/或timezone.localtime的使用,尽管我不熟悉它们。

关于日期操作,datetime.astimezone()返回一个新的日期时间,而不是就地转换。您需要将转换后的值分配回case.uploaded_on

for case in cases:
    case.uploaded_on = case.uploaded_on.astimezone(pytz.timezone(user.timezone))

关于是否可以在单个JSON响应中传递多个查询集,可以使用itertools.chain来实现这一点。

from itertools import chain
return JsonResponse(serializers.serialize('json', chain(cases, cases2)), safe=False)

最新更新