前几天做项目的时,由于form数据是通过ajax过去的,发现了一个很蛋疼的问题。
post数据
{
'test': 'test'
}
handler代码片段
form = TestForm(json.loads(self.request.body))
打印form.data的时候哥华丽丽傻眼了
{
'test': 't'
}
后来看了下wtforms的源码找到了问题, 原来wtforms构造数据的格式要求是value的值是必须要用’[]’包含起来的,也就是说value必须是个list类型的。然后遍历dict(也就是form数据)的数据时,会把value[0]取出来,而对于字符串而言’test’而言的,得到自然也就是’t’啦。
解决方案:
1.直接修改模块源码(不推荐,至于为什么下面再说)
2.新建一个类继承Form,修改相关方法
方案1之所以不推荐,是因为通常第三模块都是通过pip/easy_install安装,不方便项目的部署也不方便项目其他人的工作。如果把模块文件直接放在项目也可以,但这样是非常不好的python实践,会让项目目录结构变得复杂冗余,也不方便对项目的第三方模块管理(比如说在新的电脑配置项目时,明明包在却由于相关依赖没有满足,模块工作不了时无法排错,如果相关模块要升级的,对团队和部署会造成不必要的时间成本之类的情况)
附上方案2的代码,mark下也为了其他人碰上这种问题时可以很快的解决问题,回头有空会把代码提交到wtforms-tornado项目里(开源万岁,github万岁:D)
在forms.py文件里或放在一个专门的文件/文件夹里添加如下代码
from wtforms_tornado import Form
class BaseForm(Form):
"""
fix wtform-tornado bug when form data from request.body
"""
def __init__(self, formdata=None, obj=None, prefix='', locale_code='en_US',
**kwargs):
self._locale_code = locale_code
formdata = self.fix_form_data(formdata)
super(Form, self).__init__(formdata, obj, prefix, **kwargs)
def fix_form_data(self, form_data):
for field, value in form_data.items():
if not type(value) == type([]):
form_data[field] = [value]
return form_data