Dữ liệu JSON của tôi ở đâu trong yêu cầu Django đến của tôi?


162

Tôi đang cố xử lý các yêu cầu JSON / Ajax đến với Django / Python.

request.is_ajax()Truetheo yêu cầu, nhưng tôi không biết trọng tải ở đâu với dữ liệu JSON.

request.POST.dir chứa cái này:

['__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']

Rõ ràng là không có chìa khóa trong các phím bài yêu cầu.

Khi tôi nhìn vào POST trong Fireorms , có dữ liệu JSON được gửi trong yêu cầu.


Bạn đang thực sự đăng bài là gì? Chỉ cho chúng tôi cuộc gọi javascript.
Daniel Roseman

len(request.POST)request.POST.items()cũng sẽ giúp đỡ.
Vinay Sajip

Câu trả lời:


233

Nếu bạn đang đăng JSON lên Django, tôi nghĩ bạn muốn request.body( request.raw_post_datatrên Django <1.4). Điều này sẽ cung cấp cho bạn dữ liệu JSON thô được gửi qua bài viết. Từ đó bạn có thể xử lý nó hơn nữa.

Dưới đây là một ví dụ sử dụng JavaScript, jQuery , jquery-json và 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")

Vui lòng giải thích ý của bạn về 'khách hàng thử nghiệm'? Bạn đang cố làm gì vậy?
Jared Knipp

Tôi không cố tỏ ra thô lỗ: Bởi "khách hàng thử nghiệm", ý tôi là "khách hàng thử nghiệm" của django. Làm thế nào để bạn kiểm tra lượt xem nếu không phải với khách hàng thử nghiệm?
jMstyle

4
Hãy ghi nhớ: Bạn nên kết thúc url bằng dấu gạch chéo (/) char. Đồng thời vô hiệu hóa CSRF với @csrf_exeem
dani herrera

46
NB nếu bạn đang sử dụng 1.4 thì đây sẽ được gọi là request.body. raw_post_data không được dùng nữa ...
Prauchfuss

3
để thử nghiệm với django unittest chỉ cần làmself.client.post('/event/save-json/', json.dumps(python_dict), HTTP_X_REQUESTED_WITH='XMLHttpRequest', content_type="application/json")
Guillaume Vincent

67

Tôi đã từng gặp vấn đề tương tự. Tôi đã đăng một phản hồi JSON phức tạp và tôi không thể đọc dữ liệu của mình bằng từ điển request.POST.

Dữ liệu POST JSON của tôi là:

//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);

Trong trường hợp này, bạn cần sử dụng phương pháp được cung cấp bởi aurealus. Đọc request.body và deserialize nó với 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
Tôi đang gặp vấn đề với dòng thứ 4: json_data = simplejson.loads(request.raw_post_data)bạn có chắc là đã nêu chính xác không?
wfbarksdale

Tôi khá chắc chắn rằng request.raw_post_data là hình thức chính xác như tôi đã sử dụng ví dụ này trong thử nghiệm. Bạn có vấn đề gì với @weezybizzle?
stricjux

1
Dữ liệu đến trong một số văn bản bổ sung cũng được nối thêm vào đó đang làm rối loạn việc phân tích cú pháp. Vì vậy, nó là 100% tôi.
wfbarksdale

4
django.utils.simplejsonđã được gỡ bỏ trong các phiên bản gần đây. Chỉ cần sử dụng jsonthư viện stdlib .
Martijn Pieters

Bạn sẽ muốn sử dụng request.body thay vì request.raw_post_data cho Django 1.4+
mrooney

38

Phương pháp 1

Khách hàng: Gửi dưới dạng 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}

Người phục vụ :

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

Cách 2

Khách hàng: Gửi dưới dạng x-www-form-urlencoded
(Lưu ý: contentType& processDatađã thay đổi, JSON.stringifykhông cần thiết)

$.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

Người phục vụ :

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

Đã thay đổi trong 1.5+: https://docs.djangoproject.com/en/dev/release/1.5/#non-form-data-in-http-requests

Dữ liệu không phải dạng trong các yêu cầu HTTP :
request.POST sẽ không còn bao gồm dữ liệu được đăng qua các yêu cầu HTTP với các loại nội dung không cụ thể trong tiêu đề. Trong các phiên bản trước, dữ liệu được đăng với các loại nội dung không phải là dữ liệu đa dữ liệu / biểu mẫu hoặc ứng dụng / x-www-form-urlencoding vẫn sẽ được đại diện trong thuộc tính request.POST. Các nhà phát triển muốn truy cập dữ liệu POST thô cho các trường hợp này, nên sử dụng thuộc tính request.body để thay thế.

Có lẽ liên quan


3
Re 1 -django.http.request.RawPostDataException: You cannot access body after reading from request's data stream
AlxVallejo 15/03/18

24

Điều quan trọng cần nhớ là Python 3 có một cách khác để biểu diễn các chuỗi - chúng là các mảng byte.

Sử dụng Django 1.9 và Python 2.7 và gửi dữ liệu JSON trong phần chính (không phải tiêu đề), bạn sẽ sử dụng một cái gì đó như:

mydata = json.loads(request.body)

Nhưng đối với Django 1.9 và Python 3.4 bạn sẽ sử dụng:

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

Tôi vừa trải qua giai đoạn học tập này để tạo ra ứng dụng Py3 Django đầu tiên của tôi!


3
Cảm ơn bạn đã giải thích của bạn! Tôi đang sử dụng Django 1.10 và Python 3.5, mydata = json.loads (request.body.decode ("utf-8")) hoạt động!
Julia Zhao


9

trên django 1.6 trăn 3.3

khách hàng

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

người phục vụ

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

Tải trọng HTTP POST chỉ là một bó byte phẳng. Django (giống như hầu hết các khung công tác) giải mã nó thành một từ điển từ các tham số được mã hóa URL hoặc mã hóa MIME-multiart. Nếu bạn chỉ đổ dữ liệu JSON vào nội dung POST, Django sẽ không giải mã nó. Hoặc là giải mã JSON từ nội dung POST đầy đủ (không phải từ điển); hoặc đặt dữ liệu JSON vào trình bao bọc nhiều phần MIME.

Tóm lại, hiển thị mã JavaScript. Vấn đề dường như là có.


Tôi thấy vấn đề bây giờ! Tham số type = 'json' trong jquery đề cập đến loại mong đợi, không phải những gì nó gửi. Đó là gửi dữ liệu được mã hóa dạng bài đăng thông thường, vì vậy nếu tôi muốn gửi "json", tôi cần chuyển đổi nó thành một chuỗi và chuyển "json = {foo: bar,}", v.v. Tuy nhiên, tôi không thể tin rằng đó là Làm thế nào hầu hết mọi người làm điều đó. Tôi phải thiếu một cái gì đó ở đây.

Thực tế bạn có thể chuyển đổi biểu mẫu thành một chuỗi JSON trong jQuery với hàm .serialize (). Nhưng tại sao bạn đặc biệt cần gửi json, mặc dù? Có gì sai khi chỉ gửi dữ liệu biểu mẫu?
Daniel Roseman

4
Có nhiều trường hợp dữ liệu dạng thô không đủ; JSON cho phép bạn gửi các đối tượng phân cấp, không chỉ các cặp khóa: giá trị. Bạn có thể gửi các tập hợp, mảng, v.v. Bạn có thể làm tất cả điều đó với dữ liệu bài đăng, nhưng nó không thuận tiện. Thật tuyệt khi luôn luôn đối phó với JSON, cả đến và đi
taxilian

5

request.raw_post_datađã bị phản đối Sử dụng request.bodythay thế


Cảm ơn bạn vì điều này! Làm việc hoàn hảo.
Prometheus

4

Một cái gì đó như thế này. Nó hoạt động: Yêu cầu dữ liệu từ khách hàng

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);
});

Yêu cầu xử lý tại máy chủ

@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

Sử dụng Angular, bạn nên thêm tiêu đề để yêu cầu hoặc thêm nó vào tiêu đề cấu hình mô-đun: {'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 chỉ là một đối tượng giống như từ điển, vì vậy chỉ cần lập chỉ mục vào nó với cú pháp chính tả.

Giả sử trường biểu mẫu của bạn được fred, bạn có thể làm một cái gì đó như thế này:

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

Cách khác, sử dụng một đối tượng biểu mẫu để đối phó với dữ liệu POST.


Tôi đã tìm kiếm trong request.POST ['json'] không chứa gì. len là 0

Sau đó, nó chắc chắn sẽ giúp xem cuộc gọi JavaScript của bạn, như Daniel đề xuất.
Vinay Sajip

13
request.POST chỉ được điền khi phần thân của yêu cầu POST được mã hóa Form, nếu không thì nó trống.
slacy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.