Di mana data JSON saya dalam permintaan Django masuk saya?

162

Saya mencoba memproses permintaan JSON / Ajax yang masuk dengan Django / Python.

request.is_ajax()ada Truedi permintaan, tapi saya tidak tahu di mana payload adalah dengan data JSON.

request.POST.dir berisi ini:

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

Tampaknya tidak ada kunci dalam kunci posting permintaan.

Ketika saya melihat POST di Firebug , ada data JSON yang dikirim dalam permintaan.

Flimm
sumber
Apa yang sebenarnya Anda POSTing? Tunjukkan kami panggilan javascript.
Daniel Roseman
Dan len(request.POST)dan request.POST.items()juga akan membantu.
Vinay Sajip

Jawaban:

233

Jika Anda memposting JSON ke Django, saya pikir Anda mau request.body( request.raw_post_datadi Django <1.4). Ini akan memberi Anda data JSON mentah yang dikirim melalui pos. Dari sana Anda dapat memprosesnya lebih lanjut.

Ini adalah contoh menggunakan JavaScript, jQuery , jquery-json dan 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
sumber
Tolong jelaskan apa yang Anda maksud dengan 'klien uji'? Apa yang sedang Anda coba lakukan?
Jared Knipp
Saya tidak berusaha bersikap kasar: Dengan "klien uji," maksud saya Django "klien uji." Bagaimana Anda menguji tampilan jika tidak dengan klien uji?
jMyles
4
Perlu diingat: Anda harus mengakhiri url dengan char slash (/). Nonaktifkan CSRF dengan @csrf_exempt
dani herrera
46
NB jika Anda menggunakan 1.4 ini akan disebut request.body. raw_post_data sudah tidak digunakan lagi ...
prauchfuss
3
untuk menguji dengan Django Unittest lakukanself.client.post('/event/save-json/', json.dumps(python_dict), HTTP_X_REQUESTED_WITH='XMLHttpRequest', content_type="application/json")
Guillaume Vincent
68

Saya memiliki masalah yang sama. Saya telah memposting respons JSON yang kompleks, dan saya tidak bisa membaca data saya menggunakan kamus request.POST.

Data JSON POST saya adalah:

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

Dalam hal ini Anda perlu menggunakan metode yang disediakan oleh aurealus. Baca request.body dan deserialize dengan 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")
stricjux
sumber
2
Saya mengalami masalah dengan baris ke-4: json_data = simplejson.loads(request.raw_post_data)apakah Anda yakin menyatakannya dengan benar?
wfbarksdale
Saya cukup yakin bahwa request.raw_post_data adalah formulir yang benar karena saya menggunakan contoh ini dalam pengujian. Masalah apa yang Anda miliki di @weezybizzle?
stricjux
1
Data yang datang dalam beberapa teks tambahan ditambahkan juga yang mengacaukan parsing. Jadi 100% saya.
wfbarksdale
4
django.utils.simplejsontelah dihapus dalam versi terbaru. Cukup gunakan jsonperpustakaan stdlib .
Martijn Pieters
Anda akan ingin menggunakan request.body alih-alih request.raw_post_data untuk Django
1.4+
38

Metode 1

Klien: Kirim sebagai 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}

Server:

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

Metode 2

Klien: Kirim sebagai x-www-form-urlencoded
(Catatan: contentType& processDatatelah berubah, JSON.stringifytidak diperlukan)

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

Server:

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

Berubah dalam 1,5+: https://docs.djangoproject.com/en/dev/releases/1.5/#non-form-data-in-http-requests

Data non-formulir dalam permintaan HTTP :
request.POST tidak akan lagi menyertakan data yang dikirim melalui permintaan HTTP dengan tipe konten non-spesifik di header. Dalam versi sebelumnya, data yang diposting dengan tipe konten selain multipart / form-data atau aplikasi / x-www-form-urlencoded akan tetap terwakili dalam atribut request.POST. Pengembang yang ingin mengakses data POST mentah untuk kasus ini, harus menggunakan atribut request.body.

Mungkin terkait

pengguna
sumber
3
Re 1 -django.http.request.RawPostDataException: You cannot access body after reading from request's data stream
AlxVallejo
24

Penting untuk diingat bahwa Python 3 memiliki cara berbeda untuk merepresentasikan string - yaitu byte array.

Menggunakan Django 1.9 dan Python 2.7 dan mengirim data JSON di badan utama (bukan header) Anda akan menggunakan sesuatu seperti:

mydata = json.loads(request.body)

Tetapi untuk Django 1.9 dan Python 3.4 Anda akan menggunakan:

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

Saya baru saja melalui kurva pembelajaran ini membuat aplikasi Py3 Django pertama saya!

Richard Cooke
sumber
3
Terima kasih atas penjelasan Anda! Saya menggunakan Django 1.10 dan Python 3.5, mydata = json.loads (request.body.decode ("utf-8")) berfungsi!
Julia Zhao
23

request.raw_responsesekarang sudah ditinggalkan. Gunakan request.bodysebagai gantinya untuk memproses data formulir non-konvensional seperti muatan XML, gambar biner, dll.

Dokumentasi Django tentang masalah ini .

Kevin S Lin
sumber
9

pada django 1.6 python 3.3

klien

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

server

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")))
Bebek karet
sumber
5

Payload HTTP POST hanya setumpuk byte. Django (seperti kebanyakan kerangka kerja) menerjemahkannya ke dalam kamus dari parameter yang disandikan URL, atau penyandian MIME-multipart. Jika Anda hanya membuang data JSON dalam konten POST, Django tidak akan memecahkan kode itu. Entah melakukan JSON decoding dari konten POST lengkap (bukan kamus); atau memasukkan data JSON ke bungkus MIME-multipart.

Singkatnya, perlihatkan kode JavaScript. Masalahnya tampaknya ada di sana.

Javier
sumber
Saya melihat masalahnya sekarang! Parameter type = 'json' di jquery mengacu pada tipe apa yang diharapkan, bukan apa yang dikirimkannya. Ia mengirimkan data yang dikodekan dari pos formulir biasa, jadi jika saya ingin mengirim "json" saya perlu mengubahnya menjadi string, dan meneruskan "json = {foo: bar,}" dll. Namun saya tidak percaya, bahwa itu bagaimana kebanyakan orang melakukannya. Saya pasti kehilangan sesuatu di sini.
Sebenarnya Anda bisa mengonversi formulir ke string JSON di jQuery dengan fungsi .serialize (). Tetapi mengapa Anda terutama perlu mengirim json? Apa yang salah dengan mengirim data formulir?
Daniel Roseman
4
Ada banyak kasus di mana data formulir mentah tidak cukup; JSON memungkinkan Anda untuk mengirim objek hierarkis, bukan hanya kunci: pasangan nilai. Anda dapat mengirim set bersarang, array, dll. Anda mungkin bisa melakukan semua itu dengan data posting, tetapi itu tidak nyaman. Agak baik untuk selalu berurusan dengan JSON, baik ke dan dari
taxilian
5

request.raw_post_datatelah ditinggalkan. Gunakan request.bodysebagai gantinya

Andres
sumber
Terima kasih untuk ini! Bekerja dengan sempurna.
Prometheus
4

Sesuatu seperti ini. Berhasil: Meminta data dari klien

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

Memproses permintaan di server

@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")
Nghia Tu
sumber
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))
Rajan Mandanka
sumber
-2

Menggunakan Angular Anda harus menambahkan header untuk meminta atau menambahkannya ke header konfigurasi modul: {'Content-Type': 'application/x-www-form-urlencoded'}

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

request.POST hanyalah objek seperti kamus, jadi cukup indeks saja dengan sintaks dict.

Dengan asumsi bidang formulir Anda fred, Anda bisa melakukan sesuatu seperti ini:

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

Sebagai alternatif, gunakan objek formulir untuk menangani data POST.

Michael van der Westhuizen
sumber
Saya mencari dalam permintaan. POST ['json'] yang tidak mengandung apa-apa. len adalah 0
Maka pasti akan membantu untuk melihat panggilan JavaScript Anda, seperti yang disarankan Daniel.
Vinay Sajip
13
request.POST hanya diisi ketika tubuh permintaan POST dikodekan Formulir, jika tidak maka kosong.
slacy