django Piston POST 请求将字符串转换为列表
我有一个简单的Django-Piston处理器,它用来创建一个模型的新实例并保存它。
从客户端,我使用JavaScript对象和JQuery.post来发送数据。
通过Firebug查看数据时,发送的字符串看起来是这样的:
classification=&organization=&title=Formatting+Test+7&description=test&created_by=created_on=&last_modified=&csrfmiddlewaretoken=a8352bb51f88c271119a81228a5c291f
可以看到,只有标题、描述和csrfmiddlewaretoken被设置了。
在Piston处理器的create方法顶部,在其他代码运行之前,我打印了request.POST:
print 'POST:', request.POST
这在Django开发服务器的输出中打印出以下内容:
POST: <QueryDict: {u'description': [u'test'], u'classification': [u''], u'title': [u'Formatting Test 7'], u'created_by': [u''], u'created_on': [u''], u'last_modified': [u''], u'organization': [u''], u'csrfmiddlewaretoken': [u'a8352bb51f88c271119a81228a5c291f']}>
如你所见,所有数据现在都变成了列表。当我使用Django表单保存数据时,它会把列表转换成字符串,而当数据在客户端显示时,原本应该是“Formatting Test 7”,却显示成了“[u'Formatting Test 7']”。
在网上搜索似乎没有找到遇到同样问题的人,我已经使用Piston超过6个月,从来没有见过这样的错误。
编辑:正如JPIC所说,我以为我遇到的错误其实不是错误,而是设计使然。我的问题在于在使用Django表单之前扩展了QuerySet中的数据。
错误的做法:
some_initial_data = {
'created_by': creator.pk,
'organization': org.pk,
'classification': 7
}
post = dict(request.POST)
post.update(some_initial_data)
form = MyModelForm(post)
正确的做法:
如在QueryDict的更新方法中所描述的:https://docs.djangoproject.com/en/1.3/ref/request-response/#querydict-objects
some_initial_data = {
'created_by': creator.pk,
'organization': org.pk,
'classification': 7
}
post = request.POST.copy()
post.update(initial_data)
form = MyModelForm(post)
1 个回答
这不是错误,你的数据一直都是这样的列表,这是Django的一个设计选择。任何访问QueryDict实例并且用除了getlist()
方法以外的方式获取列表值的代码,都是在错误地使用QueryDict。
QueryDict允许一个键有多个值,比如说:foo=bar&foo=test
,你的QueryDict会变成{u'foo': [u'bar', u'test']}
。
举个例子,如果你有?foo=bar&foo=test&x=y
:
ipdb> request.GET
<QueryDict: {u'x': [u'y'], u'foo': [u'bar', u'test']}>
ipdb> request.GET['x']
u'y'
ipdb> request.GET.getlist('x')
[u'y']
ipdb> request.GET['foo']
u'test'
ipdb> request.GET.getlist('foo')
[u'bar', u'test']
如你所见,QueryDict是一个包含列表的字典,默认情况下不会直接返回实际的列表:它会像普通字典一样工作。所以如果某段代码在获取列表,那就是在错误地使用QueryDict。
值得一提的是,如果你想用$.post(url, {'foo':['bar', 'test']})
,你需要调用$.ajaxSettings.traditional = true!
这在处理复选框或多选框时特别有用。如果我说错了请纠正我,但这是标准做法,而PHP的方式foo[]=bar&foo[]=test并不是标准。