208 votes

Où sont mes données JSON dans ma requête Django entrante ?

J'essaie de traiter les requêtes JSON/Ajax entrantes avec Django/Python.

request.is_ajax() es True sur la requête, mais je n'ai aucune idée de l'endroit où se trouve la charge utile avec les données JSON.

request.POST.dir contient ceci :

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

Il n'y a apparemment pas de clés dans le poste de demande de clés.

Quand je regarde le POST dans Firebug il y a des données JSON envoyées dans la requête.

267voto

Jared Knipp Points 1855

Si vous envoyez JSON à Django, je pense que vous voulez request.body ( request.raw_post_data sur Django < 1.4). Vous obtiendrez ainsi les données JSON brutes envoyées par le courrier. À partir de là, vous pouvez les traiter davantage.

Voici un exemple utilisant JavaScript, jQuery , jquery-json et 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")

91voto

stricjux Points 600

J'ai eu le même problème. J'avais posté une réponse JSON complexe, et je ne pouvais pas lire mes données en utilisant le dictionnaire request.POST.

Mes données JSON POST étaient :

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

Dans ce cas, vous devez utiliser la méthode fournie par aurealus. Lisez le request.body et désérialisez-le avec la stdlib json.

#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")

47voto

buffer Points 2261

Méthode 1

Client : Envoyer en tant que 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}

Serveur :

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

Méthode 2

Client : Envoyer en tant que x-www-form-urlencoded
(Note : contentType & processData ont changé, JSON.stringify n'est pas nécessaire)

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

Serveur :

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

Modifié en 1.5+ : https://docs.djangoproject.com/en/dev/releases/1.5/#non-form-data-in-http-requests

Données non formelles dans les requêtes HTTP :
request.POST n'inclura plus les données postées via les requêtes HTTP avec des types de contenu non spécifiques au formulaire dans l'en-tête. Dans les versions précédentes, les données postées avec des types de contenu autres que multipart/form-data ou application/x-www-form-urlencoded finissaient toujours par être représentées dans l'en-tête l'attribut request.POST. Les développeurs souhaitant accéder aux données brutes POST brutes pour ces cas, doivent utiliser l'attribut request.body à la place.

Probablement lié

29voto

Richard Cooke Points 28

Il est important de se rappeler que Python 3 a une façon différente de représenter les chaînes de caractères - ce sont des tableaux d'octets.

En utilisant Django 1.9 et Python 2.7 et en envoyant les données JSON dans le corps principal (et non dans un en-tête), vous utiliserez quelque chose comme :

mydata = json.loads(request.body)

Mais pour Django 1.9 et Python 3.4, vous utiliserez :

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

Je viens de passer par cette courbe d'apprentissage en réalisant ma première application Py3 Django !

23voto

Kevin S Lin Points 367

request.raw_response est maintenant déprécié. Utilisez request.body au lieu de traiter des données de forme non conventionnelle telles que des charges utiles XML, des images binaires, etc.

Documentation de Django sur la question .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X