【问题标题】:Marshmallow treating timestamp differently depending on the machine runing itMarshmallow 根据破坏时间戳的机器对时间戳的处理方式不同
【发布时间】:2017-05-05 12:26:46
【问题描述】:

我正在使用 Flask 在 python 中开发一个 REST API。我使用 SQLalchemy 和 Marshmallow 来处理和存储进出 API 的数据。

我有一条用于创建事件的路线。它需要一个日期时间作为 POST 有效负载的信息之一。在模型中,此字段使用 TIMESTAMP 类型。 SQLalchemy 的 TIMESTAMP 类型是支持时区的日期时间。

当我在 Linux 上运行 API 时,一切正常,但当我在 Windows 上运行它时,数据进来了,因为它应该从棉花糖的模式中传递到 load() 方法中
post_campaign, errors = campaign_schema.load(request.get_json()) 一旦将其加载到架构中,日期时间就会丢失时区数据,这对我来说是个大问题。

我没有在我的架构中做任何特殊操作,它是一种“经典”的架构。

基本上,在我的机器和其他一些机器上,我有

test_campaign (tests.test_setup.Testing) ...

现在 2017-05-05 09:52:39.014386+00:00 生成 datetime.utcnow().replace(tzinfo=pytz.utc)
在加载模式 2018-05-05 08:35:17.361864+00:00
架构中的数据 2018-05-05 08:35:17.361864+00:00

在我拥有的其他机器上

test_campaign (tests.test_setup.Testing) ...

现在 2017-05-05 09:52:39.014386+00:00
在加载模式 2018-05-05 08:35:17.361864+00:00
架构中的数据 2018-05-05 08:35:17

我的架构(ma 是棉花糖):

class CampaignSchema(ma.ModelSchema):
   class Meta:
   model = Campaign
admingroup_id = field_for(Campaign, 'admingroup_id', dump_only=False)
smtp_id = field_for(Campaign, 'smtp_id', dump_only=False)
mail_template_id = field_for(Campaign, 'mail_template_id', dump_only=False)
landing_page_id = field_for(Campaign, 'landing_page_id', dump_only=False)

campaign_schema = CampaignSchema()
campaigns_schema = CampaignSchema(many=True)

你们中有人知道这种行为吗?

【问题讨论】:

    标签: python datetime marshmallow


    【解决方案1】:

    TL;DR
    您需要在您使用的任何机器上安装dateutil 模块:

    pip install python-dateutil
    

    棉花糖Schema也有类似的问题:

    class TestSchema(Schema):
        dt_field = fields.DateTime(required=True)
    

    按原样使用它,我得到了一个不知道时区的 datetime 对象:

    >>> ts = TestSchema()
    >>> ts.load({'dt_field': '2018-03-22T16:30:00+02:00'}).data.get('dt_field')
    datetime.datetime(2018, 3, 22, 16, 30)
    

    marshmallow 有一个 utils.py,其中包含各种方法。
    其中一些方法用于将日期时间字符串转换为datetime 对象,例如from_iso_datetime()

    def from_iso_datetime(datestring, use_dateutil=True):
           """
           Parse an ISO8601-formatted datetime string and return a datetime object.
           Use dateutil's parser if possible and return a timezone-aware datetime.
           """
        if not _iso8601_re.match(datestring):
            raise ValueError('Not a valid ISO8601-formatted datetime string')
        # Use dateutil's parser if possible
        if dateutil_available and use_dateutil:
            return parser.parse(datestring)
        else:
            # Strip off timezone info.
            return datetime.datetime.strptime(datestring[:19], '%Y-%m-%dT%H:%M:%S')
    

    从这段代码 sn-p 中,我们可以看到该方法检查dateutils 是否可用,如果不可用,它会剥离时区信息。

    当我安装dateutils(从而使其对marshmallow“可用”)时,上面的示例按预期工作:

    >>> ts.load({'dt_field': '2018-03-22T16:30:00+02:00'}).data.get('dt_field')
    datetime.datetime(2018, 3, 22, 16, 30, tzinfo=tzoffset(None, 7200))
    

    【讨论】:

      猜你喜欢
      • 2020-05-17
      • 2015-03-07
      • 1970-01-01
      • 2018-07-08
      • 1970-01-01
      • 2016-10-21
      • 1970-01-01
      • 2016-07-11
      • 1970-01-01
      相关资源
      最近更新 更多