【问题标题】:Where's my JSON data in my incoming Django request?我传入的 Django 请求中的 JSON 数据在哪里?
【发布时间】:2010-11-15 12:52:30
【问题描述】:

我正在尝试使用 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() 也会有所帮助。

标签: python ajax json django content-type


【解决方案1】:

如果您将 JSON 发布到 Django,我认为您需要 request.body(在 Django request.raw_post_data)。这将为您提供通过帖子发送的原始 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);
    }
});

姜戈:

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

Django

  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 的“测试客户端”。如果不使用测试客户端,你如何测试视图?
  • 请记住:您应该以斜杠 ( / ) 字符结束 url。还可以使用 @csrf_exempt 禁用 CSRF
  • 注意,如果您使用的是 1.4,这将被称为 request.body 。 raw_post_data 已弃用...
  • 使用 django unittest 进行测试只需执行self.client.post('/event/save-json/', json.dumps(python_dict), HTTP_X_REQUESTED_WITH='XMLHttpRequest', content_type="application/json")
【解决方案2】:

我遇到了同样的问题。我一直在发布一个复杂的 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);

在这种情况下,您需要使用 aurealus 提供的方法。读取 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")

【讨论】:

  • 我在第 4 行遇到问题:json_data = simplejson.loads(request.raw_post_data) 你确定说得对吗?
  • 我很确定 request.raw_post_data 是正确的形式,因为我在测试中确实使用了这个示例。 @weezybizzle 你有什么样的问题?
  • 一些额外文本中的数据也附加了它,这破坏了解析。所以这是 100% 的我。
  • django.utils.simplejson 在最近的版本中已被删除。只需使用 stdlib json 库。
  • 对于 Django 1.4+,您需要使用 request.body 而不是 request.raw_post_data
【解决方案3】:

方法一

客户端:发送为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
(注:contentType & processData 已更改,不需要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 属性。

可能相关

【讨论】:

  • Re 1 - django.http.request.RawPostDataException: You cannot access body after reading from request's data stream
【解决方案4】:

重要的是要记住 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 应用程序的学习曲线!

【讨论】:

  • 感谢您的解释!我正在使用 Django 1.10 和 Python 3.5,mydata = json.loads(request.body.decode("utf-8")) 有效!
【解决方案5】:

request.raw_response 现已弃用。改用request.body 处理非常规的表单数据,例如 XML 有效负载、二进制图像等。

Django documentation on the issue.

【讨论】:

    【解决方案6】:

    在 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")))
    

    【讨论】:

      【解决方案7】:

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

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

      【讨论】:

      • 我现在看到了问题! jquery 中的 type='json' 参数指的是期望的类型,而不是它发送的内容。它正在发送常规形式的后编码数据,所以如果我想发送“json”,我需要以某种方式将其转换为字符串,并传递“json={foo:bar,}”等,但我不敢相信那是大多数人是如何做到的。我一定在这里遗漏了什么。
      • 其实你可以使用 .serialize() 函数将表单转换为 jQuery 中的 JSON 字符串。但是为什么你特别需要发送 json 呢?只发送表单数据有什么问题?
      • 在很多情况下,原始表单数据是不够的; JSON 允许您发送分层对象,而不仅仅是键:值对。您可以发送嵌套集、数组等。您可能可以使用发布数据完成所有这些操作,但这并不方便。总是处理 JSON 有点好,无论是往返
      【解决方案8】:

      request.raw_post_data 已被弃用。请改用request.body

      【讨论】:

        【解决方案9】:

        类似的东西。它的工作: 向客户端请求数据

        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")
        

        【讨论】:

          【解决方案10】:
          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))
          

          【讨论】:

            【解决方案11】:

            使用 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'}
            })
            

            【讨论】:

              【解决方案12】:

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

              假设你的表单域是 fred,你可以这样做:

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

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

              【讨论】:

              • 我正在查看 request.POST['json'] ,其中不包含任何内容。 len 为 0
              • 那么,正如 Daniel 建议的那样,查看您的 JavaScript 调用肯定会有所帮助。
              • request.POST 仅在 POST 请求的正文为 Form 编码时填充,否则为空。
              猜你喜欢
              • 1970-01-01
              • 2014-02-06
              • 2011-06-27
              • 1970-01-01
              • 2010-12-23
              • 2015-02-01
              • 2018-02-14
              • 2020-04-15
              相关资源
              最近更新 更多