传入的Django请求中的JSON数据在哪里?


162

我正在尝试使用Django / Python处理传入的JSON / Ajax请求。

request.is_ajax()True在请求中,但是我不知道有效负载在哪里以及JSON数据。

request.POST.dir 包含以下内容:

['__class__', '__cmp__', '__contains__', '__copy__', '__deepcopy__', '__delattr__',
 '__delitem__', '__dict__', '__doc__', '__eq__', '__ge__', '__getattribute__',
'__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__',
 '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__setitem__', '__str__', '__weakref__', '_assert_mutable', '_encoding', 
'_get_encoding', '_mutable', '_set_encoding', 'appendlist', 'clear', 'copy', 'encoding', 
'fromkeys', 'get', 'getlist', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 
'keys', 'lists', 'pop', 'popitem', 'setdefault', 'setlist', 'setlistdefault', 'update', 
'urlencode', 'values']

在请求发布键中显然没有键。

当我查看Firebug中的POST时,请求中发送了JSON数据。


您实际上在发布什么?向我们显示JavaScript调用。
丹尼尔·罗斯曼

并且len(request.POST)request.POST.items()将有所帮助。
Vinay Sajip,2009年

Answers:


233

如果您要将JSON发布到Django,我想您想要request.bodyrequest.raw_post_data在Django <1.4上)。这将为您提供通过帖子发送的原始JSON数据。从那里您可以进一步处理它。

这是一个使用JavaScript,jQuery,jquery-json和Django 的示例。

JavaScript:

var myEvent = {id: calEvent.id, start: calEvent.start, end: calEvent.end,
               allDay: calEvent.allDay };
$.ajax({
    url: '/event/save-json/',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    data: $.toJSON(myEvent),
    dataType: 'text',
    success: function(result) {
        alert(result.Result);
    }
});

Django:

def save_events_json(request):
    if request.is_ajax():
        if request.method == 'POST':
            print 'Raw Data: "%s"' % request.body   
    return HttpResponse("OK")

Django <1.4:

  def save_events_json(request):
    if request.is_ajax():
        if request.method == 'POST':
            print 'Raw Data: "%s"' % request.raw_post_data
    return HttpResponse("OK")

请解释一下“测试客户”是什么意思?你想做什么?
贾里德·纳尼普

我并不是要粗鲁:“测试客户”是指Django“测试客户”。如果不通过测试客户端,如何测试视图?
jMyles 2011年

4
请注意:您应该以斜杠(/)char结束url。还使用@csrf_exempt禁用CSRF
dani herrera

46
注意:如果您使用的是1.4,则将其称为request.body。raw_post_data已弃用...
prauchfuss 2012年

3
用Django unittest进行测试就可以了self.client.post('/event/save-json/', json.dumps(python_dict), HTTP_X_REQUESTED_WITH='XMLHttpRequest', content_type="application/json")
Guillaume Vincent

67

我有同样的问题。我一直在发布复杂的JSON响应,但无法使用request.POST字典读取数据。

我的JSON POST数据为:

//JavaScript code:
//Requires json2.js and jQuery.
var response = {data:[{"a":1, "b":2},{"a":2, "b":2}]}
json_response = JSON.stringify(response); // proper serialization method, read 
                                          // http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
$.post('url',json_response);

在这种情况下,您需要使用金黄色葡萄球菌提供的方法。阅读request.body并使用json stdlib反序列化。

#Django code:
import json
def save_data(request):
  if request.method == 'POST':
    json_data = json.loads(request.body) # request.raw_post_data w/ Django < 1.4
    try:
      data = json_data['data']
    except KeyError:
      HttpResponseServerError("Malformed data!")
    HttpResponse("Got json data")

2
我对第四行json_data = simplejson.loads(request.raw_post_data)有疑问:您确定正确地说吗?
wfbarksdale

我非常确定request.raw_post_data是正确的格式,就像我在测试中使用此示例一样。您遇到@weezybizzle是什么问题?
stricjux

1
来自一些额外文本的数据也被添加到了后面,这使解析变得更加困难。所以我是100%。
wfbarksdale

4
django.utils.simplejson在最新版本中已被删除。只需使用stdlib json库。
马丁·彼得斯

你要使用的request.body代替request.raw_post_data Django的1.4+
mrooney

38

方法一

客户:发送为 JSON

$.ajax({
    url: 'example.com/ajax/',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    processData: false,
    data: JSON.stringify({'name':'John', 'age': 42}),
    ...
});

//Sent as a JSON object {'name':'John', 'age': 42}

服务器:

data = json.loads(request.body) # {'name':'John', 'age': 42}

方法二

客户端:发送为x-www-form-urlencoded
(注意:contentTypeprocessData已更改,JSON.stringify不需要)

$.ajax({
    url: 'example.com/ajax/',
    type: 'POST',    
    data: {'name':'John', 'age': 42},
    contentType: 'application/x-www-form-urlencoded; charset=utf-8',  //Default
    processData: true,       
});

//Sent as a query string name=John&age=42

服务器:

data = request.POST # will be <QueryDict: {u'name':u'John', u'age': 42}>

在1.5+版本中进行了更改:https : //docs.djangoproject.com/en/dev/releases/1.5/#non-form-data-in-http-requests

HTTP请求中的非格式数据
request.POST将不再包含通过HTTP请求发布的数据,该数据头中包含非特定于格式的内容类型。在以前的版本中,以multipart / form-data或application / x-www-form-urlencoded以外的内容类型发布的数据仍将最终在request.POST属性中表示。对于这些情况,希望访问原始POST数据的开发人员应改用request.body属性。

可能相关


3
回复1-– django.http.request.RawPostDataException: You cannot access body after reading from request's data stream
AlxVallejo

24

重要的是要记住,Python 3以不同的方式表示字符串-它们是字节数组。

使用Django 1.9和Python 2.7并在主体(而非标头)中发送JSON数据,您将使用类似以下内容:

mydata = json.loads(request.body)

但是对于Django 1.9和Python 3.4,您可以使用:

mydata = json.loads(request.body.decode("utf-8"))

我刚刚经历了这个学习过程,制作了我的第一个Py3 Django应用!


3
谢谢你的解释!我正在使用Django 1.10和Python 3.5,mydata = json.loads(request.body.decode(“ utf-8”))有效!
朱莉娅·赵


9

在Django 1.6 python 3.3上

客户

$.ajax({
    url: '/urll/',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify(json_object),
    dataType: 'json',
    success: function(result) {
        alert(result.Result);
    }
});

服务器

def urll(request):

if request.is_ajax():
    if request.method == 'POST':
        print ('Raw Data:', request.body) 

        print ('type(request.body):', type(request.body)) # this type is bytes

        print(json.loads(request.body.decode("utf-8")))

5

HTTP POST有效负载只是一堆字节。Django(与大多数框架一样)通过URL编码参数或MIME多部分编码将其解码为字典。如果仅将JSON数据转储到POST内容中,则Django将不会对其进行解码。从完整的POST内容(而不是字典)中进行JSON解码;或将JSON数据放入MIME多部分包装器中。

简而言之,请显示JavaScript代码。问题似乎在那里。


我现在看到了问题!jQuery中的type ='json'参数指的是期望的类型,而不是发送的类型。它正在发送常规的表单后编码数据,因此,如果我想发送“ json”,我需要以某种方式将其转换为字符串,然后传递“ json = {foo:bar,}”,等等,但是我不敢相信,这就是大多数人是怎么做到的。我一定在这里想念什么。

实际上,您可以使用.serialize()函数将表单转换为jQuery中的JSON字符串。但是,为什么您特别需要发送json?仅发送表单数据有什么问题?
丹尼尔·罗斯曼

4
在许多情况下,原始表单数据是不够的。JSON允许您发送分层对象,而不仅仅是key:value对。您可以发送嵌套的集,数组等。您可能可以使用发布数据来完成所有这些操作,但这并不方便。总是
来回


4

这样的事情。它的工作原理:从客户端请求数据

registerData = {
{% for field in userFields%}
  {{ field.name }}: {{ field.name }},
{% endfor %}
}


var request = $.ajax({
   url: "{% url 'MainApp:rq-create-account-json' %}",
   method: "POST",
   async: false,
   contentType: "application/json; charset=utf-8",
   data: JSON.stringify(registerData),
   dataType: "json"
});

request.done(function (msg) {
   [alert(msg);]
   alert(msg.name);
});

request.fail(function (jqXHR, status) {
  alert(status);
});

在服务器上处理请求

@csrf_exempt
def rq_create_account_json(request):
   if request.is_ajax():
       if request.method == 'POST':
           json_data = json.loads(request.body)
           print(json_data)
           return JsonResponse(json_data)
   return HttpResponse("Error")

2
html code 

file name  : view.html


    <!DOCTYPE html>
    <html>
    <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script>
    $(document).ready(function(){
        $("#mySelect").change(function(){
            selected = $("#mySelect option:selected").text()
            $.ajax({
                type: 'POST',
                dataType: 'json',
                contentType: 'application/json; charset=utf-8',
                url: '/view/',
                data: {
                       'fruit': selected
                      },
                success: function(result) {
                        document.write(result)
                        }
        });
      });
    });
    </script>
    </head>
    <body>

    <form>
        <br>
    Select your favorite fruit:
    <select id="mySelect">
      <option value="apple" selected >Select fruit</option>
      <option value="apple">Apple</option>
      <option value="orange">Orange</option>
      <option value="pineapple">Pineapple</option>
      <option value="banana">Banana</option>
    </select>
    </form>
    </body>
    </html>

Django code:


Inside views.py


def view(request):

    if request.method == 'POST':
        print request.body
        data = request.body
        return HttpResponse(json.dumps(data))

-2

使用Angular您应该添加标头以请求或将其添加到模块配置标头: {'Content-Type': 'application/x-www-form-urlencoded'}

$http({
    url: url,
    method: method,
    timeout: timeout,
    data: data,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})

-4

request.POST只是一个类似于字典的对象,因此只需使用dict语法对其进行索引。

假设您的表单字段为fred,则可以执行以下操作:

if 'fred' in request.POST:
    mydata = request.POST['fred']

或者,使用表单对象处理POST数据。


我在找没有内容的request.POST ['json']。LEN为0

然后,如Daniel所建议的那样,一定可以帮助您查看JavaScript调用。
Vinay Sajip,2009年

13
仅当POST请求的主体为Form编码时才填充request.POST,否则为空。
slacy 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.