Gelen Django isteğimdeki JSON verilerim nerede?


162

Django / Python ile gelen JSON / Ajax isteklerini işlemeye çalışıyorum.

request.is_ajax() dır-dir True talep üzerine, ancak yük JSON verilerle hiçbir fikrim yok.

request.POST.dir bunu içerir:

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

Görünüşe göre istek posta anahtarlarında anahtar yok.

Firebug'daki POST'a baktığımda , istekte gönderilen JSON verileri var.


Aslında ne yazıyorsunuz? Bize javascript çağrısını gösterin.
Daniel Roseman

Ve len(request.POST)ve request.POST.items()de yardımcı olacaktır.
Vinay Sajip

Yanıtlar:


233

JSON'u Django'ya gönderiyorsanız, istediğinizi düşünüyorum request.body( request.raw_post_dataDjango <1.4'te). Bu size posta yoluyla gönderilen ham JSON verilerini verecektir. Oradan daha fazla işleyebilirsiniz.

JavaScript, jQuery kullanan bir örnek , jquery-json ve 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")

Lütfen 'test istemcisi' ile ne demek istediğinizi açıklayın? Ne yapmaya çalışıyorsun?
Jared Knipp

Kaba olmaya çalışmıyorum: "Test istemcisi" derken, django "test istemcisi" demek istiyorum. Test istemcisiyle değilse, görünümleri nasıl test edersiniz?
jMyles

4
Unutmayın: URL'yi eğik çizgi (/) karakteriyle sonlandırmalısınız. Ayrıca CSRF'yi @csrf_exempt ile devre dışı bırak
dani herrera

46
Eğer 1.4 kullanıyorsanız NB buna request.body denir. raw_post_data kullanımdan kaldırıldı ...
prauchfuss

3
django unittest ile test etmek sadece yapmakself.client.post('/event/save-json/', json.dumps(python_dict), HTTP_X_REQUESTED_WITH='XMLHttpRequest', content_type="application/json")
Guillaume Vincent

68

Ben de aynı problemi yaşadım. Karmaşık bir JSON yanıtı gönderiyordum ve request.POST sözlüğünü kullanarak verilerimi okuyamadım.

JSON POST verilerim:

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

Bu durumda, aurealus tarafından sağlanan yöntemi kullanmanız gerekir. İsteki okuyun. Json stdlib ile serisini kaldırın.

#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. satırla ilgili sorunlar yaşıyorum: json_data = simplejson.loads(request.raw_post_data)doğru şekilde belirtildiğinden emin misiniz?
wfbarksdale

Testte bu örneği kullandığım için request.raw_post_data'nın doğru form olduğundan eminim. @Weezybizzle ne tür sorunlarınız var?
stricjux

1
Bazı ekstra metinde gelen veriler de ayrıştırmayı berbat etti. Yani% 100 bendim.
wfbarksdale

4
django.utils.simplejson, son sürümlerde kaldırıldı. Sadece stdlib jsonkütüphanesini kullanın .
Martijn Pieters

Django 1.4+ için request.raw_post_data yerine request.body kullanmak isteyeceksiniz
mrooney

38

Yöntem 1

Müşteri: Farklı gönder 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}

Sunucu:

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

Yöntem 2

Müşteri: Farklı gönder x-www-form-urlencoded
(Not: contentType& processDatadeğişti, JSON.stringifygerekli değil)

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

Sunucu:

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

1.5+ sürümünde değişti: https://docs.djangoproject.com/en/dev/releases/1.5/#non-form-data-in-http-requests

HTTP isteklerindeki form dışı veriler :
request.POST, başlıkta forma özgü olmayan içerik türlerine sahip HTTP istekleri yoluyla yayınlanan verileri artık içermeyecektir. Önceki sürümlerde, çoklu bölüm / form verileri veya application / x-www-form-urlencoded dışındaki içerik türleriyle gönderilen veriler yine de request.POST özniteliğinde temsil edilirdi. Bu durumlar için ham POST verilerine erişmek isteyen geliştiriciler, bunun yerine request.body özelliğini kullanmalıdır.

Muhtemelen ilgili


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

24

Python 3'ün dizeleri temsil etmenin farklı bir yolu olduğunu hatırlamak önemlidir - bunlar bayt dizileridir.

Django 1.9 ve Python 2.7 kullanarak ve ana gövdede (başlık değil) JSON verilerini göndermek gibi bir şey kullanırsınız:

mydata = json.loads(request.body)

Ancak Django 1.9 ve Python 3.4 için şunları kullanırsınız:

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

Ben sadece benim ilk Py3 Django app yapma bu öğrenme eğrisi geçti!


3
Açıklamanız için teşekkürler! Django 1.10 ve Python 3.5 kullanıyorum, verilerim = json.loads (request.body.decode ("utf-8")) çalışıyor!
Julia Zhao


9

django 1.6 python 3.3 üzerinde

müşteri

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

sunucu

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 yükü yalnızca düz bir bayt bayttır. Django (çoğu çerçeve gibi) URL kodlu parametrelerden veya MIME çok parçalı kodlamadan sözlüğe şifresini çözer. JSON verilerini POST içeriğine dökerseniz, Django bu kodu çözmez. Ya tam POST içeriğinden JSON kod çözme (sözlükten değil); veya JSON verilerini bir MIME çok parçalı paketleyiciye yerleştirin.

Kısacası, JavaScript kodunu gösterin. Sorun orada gözüküyor.


Sorunu şimdi görüyorum! Jquery'deki type = 'json' parametresi, gönderdiği şeyi değil, hangi türden bekleneceğini ifade eder. Düzenli form sonrası kodlanmış veri gönderiyor, bu yüzden "json" göndermek istiyorsanız bir şekilde bir dizeye dönüştürmek ve "json = {foo: bar,}" vb geçmek gerekir, ancak bu inanamıyorum çoğu insan bunu nasıl yapıyor. Burada bir şeyi kaçırıyor olmalıyım.

Aslında formu .serialize () işleviyle jQuery içindeki bir JSON dizesine dönüştürebilirsiniz. Ama neden özellikle json göndermeniz gerekiyor? Sadece form verilerini göndermenin nesi yanlış?
Daniel Roseman

4
Ham form verilerinin yeterli olmadığı birçok durum vardır; JSON, yalnızca anahtar: değer çiftlerini değil, hiyerarşik nesneleri göndermenizi sağlar. Yuvalanmış kümeler, diziler, vb. Gönderebilirsiniz. Bunların tümünü büyük olasılıkla yazı verileriyle yapabilirsiniz, ancak bu uygun değildir. JSON ile her zaman hem anlaşma hem de anlaşma yapmak çok hoş
taxilian

5

request.raw_post_data, kullanımdan kaldırıldı. request.bodyBunun yerine kullan


Bunun için teşekkürler! Mükemmel çalıştı.
Prometheus

4

Böyle bir şey. Çalıştı: İstemciden veri isteyin

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

Sunucuda istek işleme

@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'ı kullanarak modül yapılandırma başlıklarını istemek veya eklemek için üstbilgi eklemelisiniz: {'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 yalnızca sözlük benzeri bir nesnedir, bu nedenle sözdizimi sözdizimi ile dizine ekleyin.

Form alanınızın fred olduğunu varsayarsak, böyle bir şey yapabilirsiniz:

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

Alternatif olarak, POST verileriyle ilgilenmek için bir form nesnesi kullanın.


Ben hiçbir şey içermeyen request.POST ['json'] arıyordum. len 0 oldu

Daniel'in önerdiği gibi, JavaScript çağrınızı görmeniz kesinlikle yardımcı olacaktır.
Vinay Sajip

13
POST yalnızca POST isteğinin gövdesi Form kodlu olduğunda doldurulur, aksi takdirde boştur.
slacy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.