Django的Querydict怪异行为:将POST字典捆绑为单个键

问题描述

|| 在django中使用测试客户端时,我的行为异常诡异。 我正在使用“ 0”将数据发送到我的Django应用。我通常通过iPhone应用程序和/或测试html表单执行此操作。在服务器端,这是我的处理方式:
def handle_query(request):
   print request
   q = con.QueryLog()
   q.ID = request.POST.get(\'ID\',\'\')
   q.device = request.POST.get(\'device-model\',\'\')
   ....
该打印语句看起来像您期望的那样,即post请求中的每个参数都变成了字典中的键: POST:QueryDict:{u \'app-version \':[u \'3.0 \'],u \'server-version \':[u \'v3d0 \'], 但是,我开始使用Django的测试客户端编写一些测试,无论我如何尝试,我在post请求中发送的POST参数字典都聚集在ѭ2中的单个键中。请允许我用一些代码来说明: 类SearchTest(TestCase):     def setUp():         通过
def test_search(self):
    request = HttpRequest()
    data = \'{\"amzn_locale\": \"com\"}\'
    # request._raw_post_data = data
    resp = self.client.post(
        \'/is/\',data=data,content_type=\'application/x-www-form-urlencoded\',# content_type=\'application/json\',)
服务器端的同一打印语句显示字典无法解释的分组为字符串:
POST: QueryDict: {u\'{\"amzn_locale\":\"com\"}\': [u\'\']}>,
如果我将数据设置为实际字典,同样的事情
data = {\"amzn_locale\": \"com\"}
设置请求。_raw_post_data不会更改任何内容。改变也没有
content_type=\'application/json\'
任何帮助将非常感激。从这个stackoverflow问题看来,我不是第一个遇到这个问题的人 iPhone对Django服务器的Json POST请求在QueryDict中创建QueryDict     

解决方法

        问题是您正在提供一个content_type。既然您这样做了,客户端就会期望一个类似urlencoded的字符串
\"username=hi&password=there&this_is_the_login_form=1\"
而不是像这样的字典
{\'username\': \'hi\',\'password\': \'there\',\'this_is_the_login_form\': 1}
如果您删除content_type kwarg,就可以了。 编辑:事实证明,如果您传入除MULTIPART_CONTENT之外的任何content_type,则测试客户端将查找经过url编码的字符串-content_type将仅用于确定用于对该URL编码的字符串进行编码的字符集。在此处记录。相关位为:   如果您提供content_type(例如XML有效负载的text / xml),则数据内容将使用HTTP Content-Type标头中的content_type在POST请求中按原样发送。      如果您不为content_type提供值,则数据中的值将以multipart / form-data的内容类型进行传输。在这种情况下,数据中的键值对将被编码为多部分消息,并用于创建POST数据有效负载。     ,        编辑:当然,就在我开始查看的那一行的上方,这是正确的答案。 post_data根据content_type的不同处理。请参阅下面的答案。无需应用以下更改。 因此,看起来好像发生了什么事,传递给您的数据字典立即被字符串编码函数压平为字典的字符串表示形式,该行后面的QueryDict无法读取。我不知道预期的行为是什么,但是如果在序列化发布数据之前对其进行urlencode,则它至少应以所需的形式到达QueryDict。在django / test / client.py中,我们看到第244行
post_data = smart_str(data,encoding=charset)
这只是使字典扁平化并序列化它。可能的解决方法是在序列化之前应用与GET使用的格式相同的格式,因此
post_data = smart_str(urlencode(data,doseq=True),encoding=charset)
对于我来说,这似乎是合理的,尽管我不能保证它不会在其他地方产生任何后果。看来您可以在调用client.post之前在代码中进行上面的转换,但是我还没有测试过。     ,        但是您将其声明为字符串-
data
的值周围有单引号。     

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...