Де мої дані JSON у вхідному запиті Джанго?


162

Я намагаюся обробляти вхідні запити JSON / Ajax за допомогою Django / Python.

request.is_ajax()є Trueна запит, але я не маю уявлення, де корисне навантаження з даними JSON.

request.POST.dir містить це:

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

Мабуть, немає ключів у клавішах запиту.

Коли я дивлюсь на POST у Firebug , у запиті надсилаються дані JSON.


Що ви насправді розміщуєте? Покажіть нам дзвінок javascript.
Даніель Роузман

І len(request.POST)та request.POST.items()також допоможе.
Vinay Sajip

Відповіді:


233

Якщо ви публікуєте JSON на Django, я думаю, що ви хочете request.body(request.raw_post_data на Django <1.4). Це дасть вам необроблені дані JSON, надіслані поштою. Звідти ви можете це обробити далі.

Ось приклад використання JavaScript, jQuery , jquery-json та 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);
    }
});

Джанго:

def save_events_json(request):
    if request.is_ajax():
        if request.method == 'POST':
            print 'Raw Data: "%s"' % request.body   
    return HttpResponse("OK")

Джанго <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")

Поясніть, будь ласка, що ви маєте на увазі під «тестовим клієнтом»? Що ти намагаєшся зробити?
Джаред Кніпп

Я не намагаюся бути грубим: "Тестовий клієнт", я маю на увазі "тестовий клієнт" джанго ". Як ви перевіряєте перегляди, якщо не з тестовим клієнтом?
jMyles

4
Зверніть увагу: ви повинні закінчити URL-адресу з косою (/) знаком. Також вимкніть CSRF за допомогою @csrf_exempt
dani herrera

46
Зверніть увагу: якщо ви використовуєте 1.4, це буде називатися request.body. raw_post_data застаріло ...
prauchfuss

3
тестувати на django unittest просто робиself.client.post('/event/save-json/', json.dumps(python_dict), HTTP_X_REQUESTED_WITH='XMLHttpRequest', content_type="application/json")
Гійом Вінсент

67

У мене була така ж проблема. Я публікував складну відповідь JSON, і не зміг прочитати свої дані за допомогою словника request.POST.

Мої дані JSON POST:

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

У цьому випадку потрібно скористатися методом, передбаченим ауреалусом. Прочитайте request.body і десеріалізуйте його за допомогою 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
У мене виникають проблеми з 4-м рядком: json_data = simplejson.loads(request.raw_post_data)ви впевнені, що правильно зазначено?
wfbarksdale

Я впевнений, що request.raw_post_data є правильною формою, оскільки я використовував цей приклад при тестуванні. Які проблеми у вас є @weezybizzle?
stricjux

1
Дані, що надходять у деякому додатковому тексті, також додавали його, що підкручувало розбір. Так що я був на 100%.
wfbarksdale

4
django.utils.simplejsonвидалено в останніх версіях. Просто використовуйте jsonбібліотеку stdlib .
Martijn Pieters

Ви захочете використовувати request.body замість request.raw_post_data для Django 1.4+
mrooney

38

Спосіб 1

Клієнт: Надіслати як 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}

Сервер:

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

Спосіб 2

Клієнт: Надіслати як x-www-form-urlencoded
(Примітка: contentType& processDataзмінили, JSON.stringifyне потрібно)

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

Сервер:

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

Змінено в 1,5+: https://docs.djangoproject.com/en/dev/releases/1.5/#non-form-data-in-http-requests

Неформальні дані в HTTP-запитах :
request.POST більше не включатимуть дані, розміщені через HTTP-запити з нетиповими типами вмісту в заголовку. У попередніх версіях дані, розміщені з типами вмісту, відмінними від багаточастинних / форм-даних або застосунку / x-www-form-urlencoded, як і раніше, відображатимуться в атрибуті request.POST. Розробники, які бажають отримати доступ до необроблених даних POST для цих випадків, повинні використовувати атрибут request.body замість цього.

Напевно, пов'язані


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

24

Важливо пам’ятати, що Python 3 має інший спосіб представлення рядків - вони є байтовими масивами.

Використовуючи Django 1.9 та Python 2.7 та надсилаючи дані JSON в основний корпус (а не в заголовок), ви використовуєте щось на кшталт:

mydata = json.loads(request.body)

Але для Django 1.9 та Python 3.4 ви б використовували:

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

Я щойно пройшов цю криву навчання, зробивши свій перший додаток Py3 Django!


3
Дякую за ваше пояснення! Я використовую Django 1.10 та Python 3.5, mydata = json.loads (request.body.decode ("utf-8")) працює!
Джулія Чжао


9

на django 1.6 python 3.3

клієнт

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

сервер

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 - це лише рівна купа байтів. Django (як і більшість фреймворків) розшифровує його до словника з будь-яких параметрів, кодованих URL-адресами, або MIME-багаточастинкове кодування. Якщо ви просто скиньте дані JSON у вміст POST, Django не розшифрує їх. Або декодуйте JSON з повного вмісту POST (не зі словника); або помістіть дані JSON у багатомоментну обгортку MIME.

Словом, покажіть код JavaScript. Здається, проблема є.


Я бачу проблему зараз! Параметр type = 'json' у jquery відноситься до того, якого типу очікувати, а не до того, що він надсилає. Він надсилає закодовані дані у форматі після кодування, тому якщо я хочу надіслати "json", мені потрібно якось перетворити їх у рядок і передати "json = {foo: bar,}" тощо. Я не можу повірити, однак, що це як це робить більшість людей. Я, мабуть, щось тут пропускаю.

Насправді ви можете перетворити форму в рядок JSON в jQuery за допомогою функції .serialize (). Але чому вам особливо потрібно надсилати json? Що не в тому, щоб просто надсилати дані форми?
Даніель Роузмен

4
Є багато випадків, коли необроблених даних форми недостатньо; JSON дозволяє надсилати ієрархічні об'єкти, а не просто ключ: пара значень. Ви можете надсилати вкладені набори, масиви тощо. Ви, мабуть, все це могли робити з даними публікації, але це не так зручно. Як би приємно просто завжди мати справу з JSON, як до, так і з
таксілій


4

Щось на зразок цього. Це працює: Запит даних від клієнта

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

Обробка запиту на сервері

@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, вам слід додати заголовок для запиту або додати його до заголовків конфігураційних модулів: {'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 - це просто схожий на словник об’єкт, тому просто індексуйте його синтаксисом dict.

Якщо припустити, що поле вашої форми заповнено, ви можете зробити щось подібне:

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

Крім того, використовуйте об'єкт форми для обробки даних POST.


Я шукав запит.POST ['json'], в якому нічого не було. len був 0

Тоді, безумовно, допоможе побачити ваш JavaScript-дзвінок, як запропонував Даніель.
Vinay Sajip

13
request.POST заповнюється лише тоді, коли тілом запиту POST є форма закодована, інакше вона порожня.
шибениця
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.