Onde estão meus dados JSON na minha solicitação de entrada do Django?

162

Estou tentando processar solicitações JSON / Ajax recebidas com Django / Python.

request.is_ajax()está Truena solicitação, mas não tenho idéia de onde está a carga útil com os dados JSON.

request.POST.dir contém o seguinte:

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

Aparentemente, não há chaves nas chaves de postagem de solicitação.

Quando olho para o POST no Firebug , há dados JSON sendo enviados na solicitação.

Flimm
fonte
O que você está realmente postando? Mostre-nos a chamada javascript.
21430 Daniel Roseman
E len(request.POST)e request.POST.items()também ajudaria.
Vinay Sajip 30/07/2009

Respostas:

233

Se você está postando JSON no Django, acho que você deseja request.body( request.raw_post_datano Django <1.4). Isso fornecerá os dados JSON brutos enviados pela postagem. A partir daí, você pode processá-lo ainda mais.

Aqui está um exemplo usando JavaScript, jQuery , jquery-json e 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
fonte
Por favor, explique o que você quer dizer com 'cliente de teste'? O que você está tentando fazer?
Jared Knipp 25/10
Não estou tentando ser rude: por "cliente de teste", quero dizer o "cliente de teste" do django. Como você testa vistas, se não com o cliente de teste?
jMyles
4
Lembre-se: você deve terminar o URL com barra (/) char. Também CSRF disable com @csrf_exempt
herrera dani
46
NB, se você estiver usando o 1.4, isso seria chamado request.body. O raw_post_data foi descontinuado ... #
12604
3
para testar com o django unittest basta fazerself.client.post('/event/save-json/', json.dumps(python_dict), HTTP_X_REQUESTED_WITH='XMLHttpRequest', content_type="application/json")
Guillaume Vincent
67

Eu tive o mesmo problema. Eu estava postando uma resposta JSON complexa e não conseguia ler meus dados usando o dicionário request.POST.

Meus dados JSON POST eram:

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

Nesse caso, você precisa usar o método fornecido pelo aurealus. Leia o request.body e desserialize-o com o 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
fonte
2
Estou tendo problemas com a quarta linha: json_data = simplejson.loads(request.raw_post_data)tem certeza de que foi afirmado corretamente?
wfbarksdale
Tenho certeza de que o request.raw_post_data está no formato correto, pois usei este exemplo no teste. Que tipo de problemas você tem @weezybizzle?
Stricjux 29/11
1
Os dados que apareceram em algum texto extra também o estavam atrapalhando na análise. Então era 100% eu.
wfbarksdale
4
django.utils.simplejsonfoi removido nas versões recentes. Basta usar a jsonbiblioteca stdlib .
Martijn Pieters
Você vai querer usar request.body vez de request.raw_post_data para Django 1.4 +
mrooney
38

Método 1

Cliente: Enviar como 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}

Servidor :

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

Método 2

Cliente: Enviar como x-www-form-urlencoded
(Nota: contentTypee processDataforam alterados, JSON.stringifynão é necessário)

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

Servidor :

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

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

Dados não-formulário em solicitações HTTP :
request.POST não incluirá mais dados postados por solicitações HTTP com tipos de conteúdo não específicos de formulário no cabeçalho. Nas versões anteriores, os dados postados com tipos de conteúdo diferentes de multipart / form-data ou application / x-www-form-urlencoded ainda seriam representados no atributo request.POST. Os desenvolvedores que desejam acessar os dados brutos do POST para esses casos devem usar o atributo request.body.

Provavelmente relacionado

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

É importante lembrar que o Python 3 tem uma maneira diferente de representar seqüências de caracteres - elas são matrizes de bytes.

Usando o Django 1.9 e Python 2.7 e enviando os dados JSON no corpo principal (não um cabeçalho), você usaria algo como:

mydata = json.loads(request.body)

Mas para o Django 1.9 e o Python 3.4 você usaria:

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

Acabei de passar por essa curva de aprendizado criando meu primeiro aplicativo Py3 Django!

Richard Cooke
fonte
3
Obrigado pela sua explicação! Estou usando o Django 1.10 e o Python 3.5, mydata = json.loads (request.body.decode ("utf-8")) funciona!
Julia Zhao
23

request.raw_responseagora está obsoleto. Em request.bodyvez disso, use para processar dados de formulário não convencionais, como cargas XML, imagens binárias etc.

Documentação do Django sobre o assunto .

Kevin S Lin
fonte
9

no django 1.6 python 3.3

cliente

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

servidor

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")))
Pato de borracha
fonte
5

A carga útil do HTTP POST é apenas um monte de bytes simples. O Django (como a maioria das estruturas) o decodifica em um dicionário a partir de parâmetros codificados por URL ou codificação MIME-multipart. Se você apenas despejar os dados JSON no conteúdo do POST, o Django não os decodificará. A decodificação JSON do conteúdo completo do POST (não do dicionário); ou coloque os dados JSON em um wrapper MIME com várias partes.

Em resumo, mostre o código JavaScript. O problema parece estar lá.

Javier
fonte
Eu vejo o problema agora! O parâmetro type = 'json' no jquery se refere ao tipo de expectativa, não ao que ele envia. Ele está enviando dados regulares pós-codificados, por isso, se eu quiser enviar "json", preciso convertê-lo em uma string e passar "json = {foo: bar," "etc. Não acredito, no entanto, que isso seja como a maioria das pessoas faz isso. Eu devo estar esquecendo algo aqui.
Na verdade, você pode converter o formulário em uma string JSON no jQuery com a função .serialize (). Mas por que você particularmente precisa enviar o json? O que há de errado em apenas enviar os dados do formulário?
21430 Daniel Roseman
4
Existem muitos casos em que os dados brutos do formulário não são suficientes; O JSON permite enviar objetos hierárquicos, não apenas pares chave: valor. Você pode enviar conjuntos, matrizes aninhados, etc. Você provavelmente poderia fazer tudo isso com dados de postagem, mas não é tão conveniente. É meio agradável para lidar apenas sempre com JSON, de e para
taxilian
5

request.raw_post_datafoi descontinuado. Use em request.bodyvez disso

Andres
fonte
Obrigado por isso! Funcionou perfeitamente.
Prometheus
4

Algo assim. Funcionou: Solicitar dados do cliente

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

Solicitar processo no servidor

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

Usando Angular, você deve adicionar um cabeçalho para solicitar ou adicioná-lo aos cabeçalhos de configuração do módulo: {'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
fonte
-4

request.POST é apenas um objeto semelhante a um dicionário, portanto, indexe-o com a sintaxe dict.

Supondo que o seu campo de formulário seja fred, você pode fazer algo assim:

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

Como alternativa, use um objeto de formulário para lidar com os dados do POST.

Michael van der Westhuizen
fonte
Eu estava procurando em request.POST ['json'] que não continha nada. len era 0
Definitivamente, ajudaria ver sua chamada de JavaScript, como Daniel sugeriu.
Vinay Sajip 30/07/2009
13
request.POST é preenchido apenas quando o corpo da solicitação POST é codificado em Formulário, caso contrário, está vazio.
slacy