在 Flask 中将表单 POST 对象转换为适合 mongodb 的表示形式
Posted
技术标签:
【中文标题】在 Flask 中将表单 POST 对象转换为适合 mongodb 的表示形式【英文标题】:In Flask convert form POST object into a representation suitable for mongodb 【发布时间】:2012-11-11 09:48:27 【问题描述】:我正在使用 Flask 和 MongoDB。我正在尝试将 request.form 的内容转换为适合通过 PyMongo 保存的内容。这似乎应该经常出现以提供现成的解决方案。
所以 Flask 给我的是这样的:
ImmutableMultiDict([('default', u''), ('required': u'on'), ('name', u'short_text'), ('name', u'another'), ('submit', u'Submit')])
而我想要得到的是接近这个的东西:
'default': '',
'name': ['short_text', 'another'],
'required': true
【问题讨论】:
为什么需要它?您可以像在字典中访问一样访问这些值,而无需对其进行转换。 like d['required'] 给你真实的回报。 @Abdul,如果你想循环通过 ImmutableNutiDict(),那么你可以像通常的字典一样做,但是如果你想将它作为一个整体用作一个字典,例如,使用合并字典z=**x,**y,那么它不起作用,该值周围会有方块,例如 ...,'name':['short_text'],。 【参考方案1】:>>> from werkzeug.datastructures import ImmutableMultiDict
>>> imd = ImmutableMultiDict([('default', u''), ('required', u'on'), ('name', u'short_text'), ('name', u'another'), ('submit', u'Submit')])
>>> imd.to_dict(flat=False)
>>> 'default': [''],
'name': ['short_text', 'another'],
'required': ['on'],
'submit': ['Submit']
.to_dict(flat=False)
是要记住的事情。见相关documentation
【讨论】:
只需使用.to_dict()
方法,如imd.to_dict()
。这样每个值都不是一个列表,就像在您的解决方案中一样。你也不需要导入 ImmutableMultiDict
我可能会更新这个答案以包括评论建议做的事情。 .to_dict()
的使用将是在此处将这些值作为列表删除的方法。我会保持你的答案不变,但添加它并展示使用 to_dict()
的区别。
imd.to_dict() 不合适,因为它会丢失重复的条目
imd.to_dict(flat=False)
正是 OP 正在寻找的。请参阅上面的编辑答案。
使用imd.to_dict(flat=True)
获取键/值对【参考方案2】:
Flask ImmutableMultiDict
数据结构有一个内置的to_dict
方法。
除了 Flask request
对象 form
属性是 ImmutableMultiDict
之外,这些知识还允许简单处理对 MongoDB 的表单 POST 请求。
下面是一个简单的例子:
from flask import request
@app.route('/api/v1/account', methods=['POST'])
def create_account():
"""Create user account"""
account_dict = request.form.to_dict()
db.account.insert_one(account_dict)
【讨论】:
【参考方案3】:你可以使用 werkzeug 的getlist 来写这样的代码
data = dict((key, request.form.getlist(key)) for key in request.form.keys())
现在data
的每个键都将是一个包含1 个以上元素的列表。要获得完全符合您格式的结果,请执行此操作
data = dict((key, request.form.getlist(key) if len(request.form.getlist(key)) > 1 else request.form.getlist(key)[0]) for key in request.form.keys())
现在这是低效的,因为每个键都有 3 次调用 request.form.getlist(key)
。您可以编写一个循环并绕过它。
【讨论】:
【参考方案4】:request.form.to_dict()
会产生你需要的东西
【讨论】:
【参考方案5】:python 3.6版本前后dict()
和.to_dict()
方法对比。
from werkzeug.datastructures import ImmutableMultiDict
imd = ImmutableMultiDict([('default', u''), ('required', u'on'), ('name', u'short_text'), ('name', u'another'), ('submit', u'Submit')])
到python3.5
dict(imd)
#output: 'default': [''], 'required': ['on'], 'name': ['short_text', 'another'], 'submit': ['Submit']
imd.to_dict(flat=false)
#output: 'default': [''], 'required': ['on'], 'name': ['short_text', 'another'], 'submit': ['Submit']
imd.to_dict(flat=True) # or imd.to_dict()
#output: 'default': '', 'required': 'on', 'name': 'short_text', 'submit': 'Submit'
因此,
dict(imd) == imd.to_dict(flat=False)
#output: True
从python3.6开始
dict(imd)
#output: 'default': '', 'required': 'on', 'name': 'short_text', 'submit': 'Submit'
imd.to_dict(flat=false)
#output: 'default': [''], 'required': ['on'], 'name': ['short_text', 'another'], 'submit': ['Submit']
imd.to_dict(flat=True) # or imd.to_dict()
#output: 'default': '', 'required': 'on', 'name': 'short_text', 'submit': 'Submit'
因此,
dict(imd) == imd.to_dict(flat=False)
#output: False
将.to_dict()
与flat=True/False
一起使用是更安全的选择。
【讨论】:
这太有帮助了。我复活了一个 2 年前的项目,一堆测试被打破了,我想知道这个网站到底是怎么运行的……原来正在运行的网站正在使用dict()
和 3.5。切换到 3.6 和 flat=False
。
在 Python 3.7 windows 10 上运行 dict(ImmutableMultiDict)
对我来说效果很好。当我在 Python 3.7 dict(ImmutableMultiDict)
上将项目部署到 Windows Server 2016 时,将 dict 值作为列表返回。我不得不使用.to_dict()
。【参考方案6】:
>>> from werkzeug.datastructures import ImmutableMultiDict
>>> so = ImmutableMultiDict([('default', u''), ('required', u'on'), ('name', u'short_text'), ('name', u'another'), ('submit', u'Submit')])
# Most earlier answers have comments suggesting so.to_dict()
# It doesn't work, duplicates are lost like in a normal dict
>>> so.to_dict()
'default': '', 'required': 'on', 'name': 'short_text', 'submit': 'Submit'
# The response by Vb407 is better but litters lists everywhere
>>> dso = dict(so)
'default': [''], 'required': ['on'], 'name': ['short_text', 'another'], 'submit': ['Submit']
# We can achieve the requested state by cleaning this up
>>> k: dso[k][0] if len(dso[k]) <= 1 else dso[k] for k in dso
'default': '', 'required': 'on', 'name': ['short_text', 'another'], 'submit': 'Submit'
【讨论】:
这是最佳答案。尤其是最后一种区分列表和字符串的方法是完美的。以上是关于在 Flask 中将表单 POST 对象转换为适合 mongodb 的表示形式的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Javascript 中将表单数组转换为 JSON? (对象数组)?
在 Django REST Framework 中将 GET 参数转换为 Request 对象上的 POST 数据