我正在研究使用Flask在python中创建的REST API。我使用SQLalchemy和Marshmallow来处理和存储进出API的数据。
我有一条用于创建活动的路线。它将日期时间作为POST有效负载的信息之一。在模型中,对该字段使用TIMESTAMP类型。 SQLalchemy的TIMESTAMP类型是支持时区的日期时间。
当我在Linux上运行API时,一切正常但是当我在Windows上运行它时,数据会进入,因为它应该从marshmallow的模式中传递到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()生成。替换(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是marshmallow):
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)
你们有没有人知道这种行为?
答案 0 :(得分:0)
<强> TL; DR 强>:
您需要在正在使用的任何计算机上安装dateutils
模块:
pip install python-dateutils
我遇到了类似棉花糖的问题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')
从这段代码片段中,我们可以看到该方法检查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))