ข้อมูล JSON ของฉันในคำขอ Django ที่เข้ามาของฉันอยู่ที่ไหน


162

ฉันพยายามประมวลผลคำขอ JSON / Ajax ที่เข้ามากับ Django / Python

request.is_ajax()อยู่Trueในคำขอ แต่ฉันไม่มีความคิดว่า payload อยู่กับข้อมูล 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']

เห็นได้ชัดว่าไม่มีคีย์ในคีย์การโพสต์คำขอ

เมื่อฉันดู POST ในFirebugจะมีการส่งข้อมูล JSON ในคำขอ


คุณโพสต์อะไรจริงๆ แสดงการเรียกใช้จาวาสคริปต์
Daniel Roseman

และlen(request.POST)และrequest.POST.items()ก็ยังจะช่วย
Vinay Sajip

คำตอบ:


233

หากคุณกำลังโพสต์ JSON ไปยัง Django ฉันคิดว่าคุณต้องการrequest.body( request.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")

โปรดอธิบายสิ่งที่คุณหมายถึงโดย 'ลูกค้าทดสอบ'? คุณพยายามจะทำอะไร?
Jared Knipp

ฉันไม่ได้พยายามหยาบคาย: โดย "ลูกค้าทดสอบ" ฉันหมายถึง django "ลูกค้าทดสอบ" คุณทดสอบการดูอย่างไรถ้าไม่ได้อยู่กับไคลเอนต์ทดสอบ
jMyles

4
โปรดทราบ: คุณควรวาง URL ด้วยเครื่องหมายสแลช (/) อักขระ ปิดการใช้งาน CSRF ด้วย @csrf_exempt
dani herrera

46
หมายเหตุถ้าคุณใช้ 1.4 จะเรียกว่า request.body raw_post_data เลิกใช้แล้ว ...
prauchfuss

3
เพื่อทดสอบกับ django unittest เพียงแค่ทำself.client.post('/event/save-json/', json.dumps(python_dict), HTTP_X_REQUESTED_WITH='XMLHttpRequest', content_type="application/json")
Guillaume Vincent

68

ผมมีปัญหาเหมือนกัน. ฉันโพสต์การตอบสนอง 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")

2
ฉันมีปัญหากับบรรทัดที่ 4: json_data = simplejson.loads(request.raw_post_data)คุณแน่ใจหรือว่าระบุไว้ถูกต้อง
wfbarksdale

ฉันค่อนข้างแน่ใจว่า request.raw_post_data เป็นรูปแบบที่ถูกต้องเนื่องจากฉันใช้ตัวอย่างนี้ในการทดสอบ คุณมีปัญหาอะไรกับ @weezybizzle?
stricjux

1
ข้อมูลที่มาในข้อความพิเศษบางส่วนจะถูกผนวกเข้ากับการแยกวิเคราะห์ ดังนั้นฉันจึงเป็น 100%
wfbarksdale

4
django.utils.simplejsonถูกลบในเวอร์ชันล่าสุดแล้ว เพียงใช้jsonไลบรารีstdlib
Martijn Pieters

คุณจะต้องการใช้ request.body แทนการร้องขอ
raw_post_data

38

วิธีที่ 1

ลูกค้า: ส่งเป็น 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}

วิธีที่ 2

ลูกค้า: ส่งเป็น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 ที่มีประเภทเนื้อหาที่ไม่เฉพาะเจาะจงในส่วนหัว ในเวอร์ชันก่อนหน้าข้อมูลที่โพสต์ด้วยประเภทเนื้อหาอื่นที่ไม่ใช่แบบหลายส่วน / แบบฟอร์มข้อมูลหรือแอปพลิเคชัน / x-www-form-urlencoded จะยังคงปรากฏอยู่ในแอตทริบิวต์ request.POST นักพัฒนาที่ต้องการเข้าถึงข้อมูล POST แบบดิบสำหรับกรณีเหล่านี้ควรใช้แอตทริบิวต์ request.body แทน

อาจเกี่ยวข้องกัน


3
Re 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")) ใช้งานได้!
Julia Zhao

23

request.raw_responseเลิกใช้แล้ว ใช้request.bodyแทนการประมวลผลข้อมูลในแบบฟอร์มที่ไม่ธรรมดาเช่น XML payloads, ภาพไบนารีเป็นต้น

เอกสาร Django เกี่ยวกับเรื่องนี้


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 payload เป็นเพียงแบนด์ไบต์ Django (เหมือนเฟรมเวิร์กส่วนใหญ่) ถอดรหัสเป็นพจนานุกรมจากพารามิเตอร์ที่เข้ารหัส URL หรือการเข้ารหัส MIME-multipart หากคุณเพิ่งถ่ายโอนข้อมูล JSON ในเนื้อหา POST Django จะไม่ถอดรหัส ทำการถอดรหัส JSON จากเนื้อหา POST แบบเต็ม (ไม่ใช่พจนานุกรม) หรือใส่ข้อมูล JSON ลงใน wrapper MIME-multipart

ในระยะสั้นแสดงรหัส JavaScript ดูเหมือนว่าปัญหาจะมี


ฉันเห็นปัญหาตอนนี้! พารามิเตอร์ type = 'json' ใน jquery อ้างถึงประเภทที่คาดหวังไม่ใช่สิ่งที่จะส่ง มันกำลังส่งข้อมูลที่เข้ารหัสแบบโพสต์รูปแบบปกติดังนั้นหากฉันต้องการส่ง "json" ฉันจำเป็นต้องแปลงเป็นสตริงแล้วส่งผ่าน "json = {foo: bar,}" ฯลฯ ฉันไม่อยากเชื่อเลยว่าเป็นอย่างไร คนส่วนใหญ่ทำได้อย่างไร ฉันต้องคิดถึงบางสิ่งที่นี่

จริงๆแล้วคุณสามารถแปลงฟอร์มเป็นสตริง JSON ใน jQuery ด้วยฟังก์ชัน .serialize () แต่ทำไมคุณถึงต้องส่ง json โดยเฉพาะ? เกิดอะไรขึ้นกับการส่งข้อมูลฟอร์ม?
Daniel Roseman

4
มีหลายกรณีที่ข้อมูลแบบฟอร์มดิบไม่เพียงพอ JSON อนุญาตให้คุณส่งวัตถุแบบลำดับขั้นไม่ใช่คู่คีย์: คู่ค่า คุณสามารถส่งชุดที่ซ้อนกันอาร์เรย์ ฯลฯ คุณอาจทำทุกอย่างด้วยข้อมูลการโพสต์ แต่ก็ไม่สะดวก เป็นเรื่องที่ดีที่จะจัดการกับ JSON เสมอทั้งไปและกลับ
แท็กซี่


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


ฉันกำลังมองหาคำขอ POST ['json'] ซึ่งไม่มีอะไรเลย len คือ 0

แน่นอนว่ามันจะช่วยให้เห็นการโทร JavaScript ของคุณได้อย่างแน่นอน
Vinay Sajip

13
request.POST มีการบรรจุเฉพาะเมื่อเนื้อความของคำขอ POST ถูกเข้ารหัสแบบฟอร์มมิฉะนั้นจะว่างเปล่า
slacy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.