django Piston POST 请求将字符串转换为列表

2 投票
1 回答
561 浏览
提问于 2025-04-17 12:07

我有一个简单的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 个回答

2

不是错误,你的数据一直都是这样的列表,这是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并不是标准。

撰写回答