You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF序列化器保存数据时日期字段自动变更问题求助

问题排查:DRF Serializer时间与PostgreSQL存储不一致

现象

使用Django REST Framework保存数据时,serializer.data中last_date_time显示为'2023-03-01T00:00:00+04:00',但PostgreSQL数据库中该字段实际存储为'2023-02-28 20:00:00'。

相关代码

打印的serializer.data输出

[OrderedDict([('last_price', '62.63'), ('name', None), ('country', None), 
('sector', None), ('industry', None), ('ticker', 'VUSA'), 
('high_price', 62.7075), ('last_date_time', '2023-03-01T00:00:00+04:00')])]

数据库存储值

2023-02-28 20:00:00

View的create方法

def create(self, request, *args, **kwargs):
    if self.request.user.is_superuser:
        serializer = self.get_serializer(data=request.data, many=isinstance(request.data, list))
        serializer.is_valid(raise_exception=True)
        print(serializer.data)
        self.perform_create(serializer)
        return Response({"Status": "We should be done"})

模型代码

class UsStockPriceModel(models.Model):
    ticker = models.CharField(max_length=30, blank=False, db_index=True)
    name = models.CharField(max_length=150, blank=True, null=True)  # mainly for US stocks
    country = models.CharField(max_length=100, blank=True, null=True)
    sector = models.CharField(max_length=100, blank=True, null=True)
    industry = models.CharField(max_length=100, blank=True, null=True)
    last_price = models.FloatField(blank=True, null=True)
    high_price = models.FloatField(blank=True, null=True)
    last_date_time = models.DateTimeField(db_index=True)
    created_at = models.DateTimeField(auto_now_add=True)

序列化器代码

class UsStockPriceSerializer(serializers.ModelSerializer):
    last_price = serializers.CharField(required=False, allow_null=True, allow_blank=True)
    name = serializers.CharField(required=False, allow_null=True, allow_blank=True)  # mainly for US stocks
    country = serializers.CharField(required=False, allow_null=True, allow_blank=True)
    sector = serializers.CharField(required=False, allow_null=True, allow_blank=True)
    industry = serializers.CharField(required=False, allow_null=True, allow_blank=True)

    class Meta:
        model = UsStockPriceModel
        fields = '__all__'

    def validate_last_price(self, value):
        if not value:
            return None
        try:
            return float(value)
        except ValueError:
            raise serializers.ValidationError('Valid integer is required')

问题原因

这是Django与PostgreSQL在时区处理上的正常行为:

  1. Django默认开启时区支持(USE_TZ = True),会将传入的带时区的datetime转换为UTC时间存储到PostgreSQL中。2023-03-01T00:00:00+04:00转换为UTC就是2023-02-28 20:00:00,和数据库存储值完全一致。
  2. serializer.data输出的是经过Django时区配置转换后的本地时间(对应TIME_ZONE设置的时区,此处为+4时区),所以显示的是转换后的时间。

解决方案

根据需求选择以下方式:

  • 如果希望数据库存储和serializer输出一致,且不需要UTC存储:在settings.py中设置USE_TZ = False,同时确保TIME_ZONE设置为你需要的时区(如'Asia/Dubai'对应+4时区)。注意:关闭时区支持可能引发其他时区相关问题,需谨慎评估。
  • 如果需要保持UTC存储,但希望serializer输出UTC时间:修改序列化器,为last_date_time指定DateTimeField并设置时区参数:
    last_date_time = serializers.DateTimeField(format='iso-8601', default_timezone='UTC')
    
  • 确认settings.py中的TIME_ZONE配置是否正确,确保和你预期的时区一致。

内容的提问来源于stack exchange,提问作者Sid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:45:00