Wo sind meine JSON-Daten in meiner eingehenden Django-Anfrage?

162

Ich versuche, eingehende JSON / Ajax-Anforderungen mit Django / Python zu verarbeiten.

request.is_ajax()ist Trueauf der Anfrage, aber ich habe keine Ahnung, wo sich die Nutzdaten mit den JSON-Daten befinden.

request.POST.dir enthält dies:

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

Es gibt anscheinend keine Schlüssel in den Anforderungspostschlüsseln.

Wenn ich mir den POST in Firebug ansehe , werden in der Anfrage JSON-Daten gesendet.

Flimm
quelle
Was postest du eigentlich? Zeigen Sie uns den Javascript-Aufruf.
Daniel Roseman
Und len(request.POST)und request.POST.items()würde auch helfen.
Vinay Sajip

Antworten:

233

Wenn Sie JSON in Django veröffentlichen, möchten Sie dies request.body( request.raw_post_dataauf Django <1.4). Dadurch erhalten Sie die per Post gesendeten JSON-Rohdaten. Von dort aus können Sie es weiterverarbeiten.

Hier ist ein Beispiel mit JavaScript, jQuery , jquery-json und 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
quelle
Bitte erläutern Sie, was Sie unter "Test-Client" verstehen. Was versuchst du zu machen?
Jared Knipp
Ich versuche nicht unhöflich zu sein: Mit "Testclient" meine ich den Django "Testclient". Wie testen Sie Ansichten, wenn nicht mit dem Testclient?
jMyles
4
Beachten Sie: Sie sollten die URL mit einem Schrägstrich (/) char beenden. Deaktivieren Sie auch CSRF mit @csrf_exempt
dani herrera
46
Hinweis: Wenn Sie 1.4 verwenden, wird dies als request.body bezeichnet. raw_post_data ist veraltet ...
prauchfuss
3
um mit django unittest zu testen, tu es einfachself.client.post('/event/save-json/', json.dumps(python_dict), HTTP_X_REQUESTED_WITH='XMLHttpRequest', content_type="application/json")
Guillaume Vincent
67

Ich hatte das gleiche Problem. Ich hatte eine komplexe JSON-Antwort gepostet und konnte meine Daten mit dem request.POST-Wörterbuch nicht lesen.

Meine JSON POST-Daten waren:

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

In diesem Fall müssen Sie die von Aurealus bereitgestellte Methode verwenden. Lesen Sie die request.body und deserialisieren Sie sie mit der 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
quelle
2
Ich habe Probleme mit der 4. Zeile: json_data = simplejson.loads(request.raw_post_data)Sind Sie sicher, dass dies richtig angegeben ist?
wfbarksdale
Ich bin mir ziemlich sicher, dass request.raw_post_data das richtige Formular ist, da ich dieses Beispiel beim Testen verwendet habe. Welche Probleme haben Sie bei @weezybizzle?
Stricjux
1
Die Daten, die in einem zusätzlichen Text eingingen, fügten auch das hinzu, was die Analyse vermasselte. Also war es 100% ich.
wfbarksdale
4
django.utils.simplejsonwurde in neueren Versionen entfernt. Verwenden Sie einfach die stdlib- jsonBibliothek.
Martijn Pieters
Sie möchten request.body anstelle von request.raw_post_data für Django 1.4+ verwenden
mrooney
38

Methode 1

Kunde: Senden als 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}

Methode 2

Client: Senden als x-www-form-urlencoded
(Hinweis: contentType& processDatageändert haben, JSON.stringifywird nicht benötigt)

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

Geändert in 1.5+: https://docs.djangoproject.com/de/dev/releases/1.5/#non-form-data-in-http-requests

Nicht
formulare Daten in HTTP-Anforderungen : request.POST enthält keine Daten mehr, die über HTTP-Anforderungen mit nicht formularspezifischen Inhaltstypen im Header veröffentlicht wurden. In früheren Versionen wurden Daten, die mit anderen Inhaltstypen als mehrteilig / Formulardaten oder application / x-www-form-urlencoded veröffentlicht wurden, weiterhin im Attribut request.POST dargestellt. Entwickler, die in diesen Fällen auf die POST-Rohdaten zugreifen möchten, sollten stattdessen das Attribut request.body verwenden.

Wahrscheinlich verwandt

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

Es ist wichtig, sich daran zu erinnern, dass Python 3 Zeichenfolgen auf andere Weise darstellt - es handelt sich um Byte-Arrays.

Wenn Sie Django 1.9 und Python 2.7 verwenden und die JSON-Daten im Hauptteil (kein Header) senden, verwenden Sie Folgendes:

mydata = json.loads(request.body)

Aber für Django 1.9 und Python 3.4 würden Sie verwenden:

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

Ich habe gerade diese Lernkurve durchlaufen und meine erste Py3 Django App erstellt!

Richard Cooke
quelle
3
Ich danke Ihnen für Ihre Erklärung! Ich verwende Django 1.10 und Python 3.5, mydata = json.loads (request.body.decode ("utf-8")) funktioniert!
Julia Zhao
23

request.raw_responseist jetzt veraltet. Verwenden Sie request.bodystattdessen, um nicht konventionelle Formulardaten wie XML-Nutzdaten, Binärbilder usw. zu verarbeiten.

Django-Dokumentation zu diesem Thema .

Kevin S Lin
quelle
9

auf Django 1.6 Python 3.3

Klient

$.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")))
Badeente
quelle
5

Die HTTP-POST-Nutzdaten sind nur eine flache Gruppe von Bytes. Django (wie die meisten Frameworks) dekodiert es entweder aus URL-codierten Parametern oder aus MIME-Multipart-Codierung in ein Wörterbuch. Wenn Sie nur die JSON-Daten im POST-Inhalt speichern, wird sie von Django nicht dekodiert. Führen Sie entweder die JSON-Dekodierung aus dem vollständigen POST-Inhalt (nicht aus dem Wörterbuch) durch. oder legen Sie die JSON-Daten in einem MIME-Multipart-Wrapper ab.

Kurz gesagt, zeigen Sie den JavaScript-Code. Das Problem scheint da zu sein.

Javier
quelle
Ich sehe das Problem jetzt! Der Parameter type = 'json' in jquery bezieht sich auf den zu erwartenden Typ und nicht auf den gesendeten Typ. Es werden regulär formulierte postcodierte Daten gesendet. Wenn ich also "json" senden möchte, muss ich sie irgendwie in eine Zeichenfolge konvertieren und "json = {foo: bar,}" usw. übergeben. Ich kann jedoch nicht glauben, dass dies der Fall ist wie die meisten Leute es tun. Mir muss hier etwas fehlen.
Tatsächlich können Sie das Formular mit der Funktion .serialize () in jQuery in eine JSON-Zeichenfolge konvertieren. Aber warum müssen Sie besonders json senden? Was ist falsch daran, nur die Formulardaten zu senden?
Daniel Roseman
4
Es gibt viele Fälle, in denen rohe Formulardaten nicht ausreichen. Mit JSON können Sie hierarchische Objekte senden, nicht nur Schlüssel-Wert-Paare. Sie können verschachtelte Sets, Arrays usw. senden. Sie könnten dies wahrscheinlich alles mit Post-Daten tun, aber es ist nicht so praktisch. Es ist ein bisschen schön, sich immer mit JSON zu befassen, sowohl von als auch von
Taxilian
5

request.raw_post_datawurde veraltet. Verwenden Sie request.bodystattdessen

Andres
quelle
Danke dafür! Hat perfekt funktioniert.
Prometheus
4

Etwas wie das. Es hat funktioniert: Daten vom Client anfordern

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

Anfrage auf dem Server verarbeiten

@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
quelle
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
quelle
-2

Mit Angular sollten Sie einen Header hinzufügen, um ihn anzufordern, oder ihn zu Modulkonfigurationsheadern hinzufügen: {'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
quelle
-4

request.POST ist nur ein wörterbuchähnliches Objekt, also indizieren Sie es einfach mit der Diktatsyntax.

Angenommen, Ihr Formularfeld ist fred, könnten Sie Folgendes tun:

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

Verwenden Sie alternativ ein Formularobjekt, um mit den POST-Daten umzugehen.

Michael van der Westhuizen
quelle
Ich habe auf Anfrage gesucht. POST ['json'], der nichts enthielt. len war 0
Dann wäre es definitiv hilfreich, Ihren JavaScript-Aufruf zu sehen, wie Daniel vorgeschlagen hat.
Vinay Sajip
13
request.POST wird nur ausgefüllt, wenn der Hauptteil der POST-Anforderung formularcodiert ist, andernfalls ist er leer.
Slacy