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.


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

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

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


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!


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


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

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


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


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

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

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

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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.