Django 1.11-如何确保TruncYear产生祖鲁时间 示例

我正在使用Django 1.11和Postgres 9.4。

如何确保TruncYear产生祖鲁时间(2019-10-01T00:00:00Z)。我注意到它使用这样的时区创建了日期时间(2017-01-01T00:00:00 + 03:00)

这是TruncYear查询集的代码:

from django.db.models import Count
from django.db.models.functions import TruncMonth,TruncYear,TruncDay,TruncHour

tracking_in_timeseries_data = Tracking.objects.annotate(
         year=TruncYear('created_at')).values('year','venue').annotate(
         count=Count('employee_id',distinct = True)).order_by('year') 

>>> for exp in tracking_in_timeseries_data:
...     print(exp['year'],exp['venue'],exp['count'])

2017-01-01 00:00:00+00:00 4 1
2019-01-01 00:00:00+00:00 2 2
2019-01-01 00:00:00+00:00 3 1
2019-01-01 00:00:00+00:00 4 1
2019-01-01 00:00:00+00:00 5 1
2019-01-01 00:00:00+00:00 6 1


>>> tracking_in_timeseries_data
<QuerySet [{'venue': 4,'year': datetime.datetime(2017,1,tzinfo=<UTC>),'count': 1},{'venue': 2,'year': datetime.datetime(2019,'count': 2},{'venue': 3,{'venue': 4,{'venue': 5,{'venue': 6,'count': 1}]>

如果我将其序列化,则会产生以下结果:

serializer.py

class TimeseriesYearSerializer(serializers.ModelSerializer):
    venue = VenueTSSerializer(read_only=True)
    year = serializers.DateTimeField(read_only=True)
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = Tracking
        fields = ['venue','year','count']

输出:

[
    {
      "count": 1,"year": "2017-01-01T00:00:00+03:00","venue_id": 2
    },{
      "count": 1,"year": "2018-01-01T00:00:00+03:00","venue_id": 1
    },{
      "count": 3,"year": "2019-01-01T00:00:00+03:00","venue_id": 2
    }
  ]

如何确保TruncYear queryset在Zulu时间中生成像这样的日期时间字符串,如2019-10-01T00:00:00Z,而不是时区为2019-01-01T00:00:00 + 03:00。

更新: 我注意到我通过重新启动django服务来临时修复此问题。

sudo supervisorctl stop all
sudo supervisorctl start all

然后它能够​​产生这样的Z时间2019-10-01T00:00:00Z 但是几个小时后,它开始产生像这样的时区timeformat 2017-01-01T00:00:00 + 03:00

我还注意到如果我重新启动服务器,它将没有Z时间。我必须停止并启动supervisorctl,然后暂时修复它。

这是我重启主管的代码段

/home/user/myapp/gunicorn_start.bash
/etc/supervisor/conf.d/myapp.conf
https://gist.github.com/axilaris/01525b78fcdc03071fcd34818820d7f1

这是我的服务器版本Ubuntu 16.04.3 LTS

可能是什么问题,以及如何解决它,以使其持续产生祖鲁时间。

abc123xyzzxm2000 回答:Django 1.11-如何确保TruncYear产生祖鲁时间 示例

我在这里指出的第一件事是,您使用serializers.DateTimeField--DRF doc字段表示 year ,其中 year 始终为 正整数


关于时区问题,Django在从数据库查询时使用TIME_ZONE settings。这是在进行postpost后发生的最小SQL查询,

SELECT a,b,c,DATE_TRUNC('year',"tracking_table"."created_at" AT TIME ZONE 'YOUR_TIME_ZONE_VALUE') AS "year" FROM "tracking_table

但是,幸运的是,您可以借助 tzinfo 指定 目标时区(以您的情况为UTC) > TruncYear类中的参数。

示例

import pytz

Tracking.objects.annotate(year=TruncYear('created_at',tzinfo=pytz.UTC))

要在json响应中显示 ,请将序列化器更改为

class TimeseriesYearSerializer(serializers.ModelSerializer):
    venue = VenueTSSerializer(read_only=True)
    year = serializers.IntegerField(read_only=True,source='year.year')
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = Tracking
        fields = ['venue','year','count']

参考

  1. Postgress AT TIME ZONE
  2. Postgress date_trunc
  3. DRF Serializer source argument
,

我已经检查了Django Rest Framework的来源,看起来它默认为DateTimeField使用了“ current timezone”,但是您可以通过强制传递default_timezone来强制设置它到"pytz.timezone('Zulu')"。这样,它将在所需的时区中返回字段值。

我已经玩了一点,对我来说它按预期工作。例如,Europe/Moscow用于测试序列化程序(在我的项目中),我的输出类似于

{
    "id": 1,"title": "test 123","level": 0,"slug": "test-123","icon_code": "123","image": null,"brand": false,"children": [],"created_at": "2019-12-09T01:55:08.438442+03:00"
  }

Zulu时区,我喜欢

  {
    "id": 1,"created_at": "2019-12-08T22:55:08.438442Z"
  }

我的测试字段声明是

created_at = serializers.DateTimeField(format='iso-8601',default_timezone=pytz.timezone('Zulu'))
  

似乎在您的源代码中您覆盖了“当前时区”,但未将其设置为默认时区或其他,这就是为什么它在服务器重启后立即工作并在数小时内停止(当请求设置了时区错误)。因此,您有2种方法来解决它-使用default_timezone参数像上面一样声明您的字段,或找到当前时区值在哪里更改)。对于这种情况,最简单的解决方案当然是声明所需的字段时区,但总的来说,它当然应该没有错误:)

更多信息:

本文链接:https://www.f2er.com/3143661.html

大家都在问