着信Djangoリクエストの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']

リクエストポストキーには明らかにキーがありません。

FirebugのPOSTを見ると、リクエストで送信されているJSONデータがあります。


実際に何をポストしていますか?JavaScript呼び出しを見せてください。
ダニエルローズマン

そしてlen(request.POST)request.POST.items()また役立つでしょう。
Vinay Sajip、2009

回答:


233

JSONをDjangoに投稿する場合、私はあなたが望んでいると思いますrequest.bodyrequest.raw_post_dataDjango <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);
    }
});

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、2011年

私は失礼な態度でいるつもりはありません。「テストクライアント」とは、djangoの「テストクライアント」を意味します。テストクライアントを使用しない場合、どのようにビューをテストしますか?
jMyles

4
覚えておいてください:スラッシュ(/)文字でURLを終了する必要があります。@csrf_exemptでも無効にCSRF
ダニ・エレーラ

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

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

この場合、aurealusが提供するメソッドを使用する必要があります。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最近のバージョンでは削除されました。stdlib jsonライブラリを使用するだけです。
Martijn Pieters

Django 1.4以降では、request.raw_post_dataではなくrequest.bodyを使用する必要があります
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
(注:contentTypeprocessData変更されて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リクエストを介して投稿されたデータが含まれなくなります。以前のバージョンでは、multipart / form-dataまたはapplication / x-www-form-urlencoded以外のコンテンツタイプで投稿されたデータは、依然としてrequest.POST属性で表されていました。これらのケースで生のPOSTデータにアクセスする開発者は、代わりにrequest.body属性を使用する必要があります。

おそらく関連している


3
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"))が機能します。
Julia Zhao


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はそれをデコードしません。完全なPOSTコンテンツ(辞書ではない)からJSONデコードを実行します。または、JSONデータをMIMEマルチパートラッパーに入れます。

つまり、JavaScriptコードを表示します。問題があるようです。


私は今問題を見ています!jqueryのtype = 'json'パラメーターは、送信するタイプではなく、予期されるタイプを参照します。それは通常の形式のポストエンコードされたデータを送信しているので、「json」を送信したい場合は、どういうわけかそれを文字列に変換し、「json = {foo:bar、}」などを渡す必要がありますが、それは信じられません。ほとんどの人がそれをどのように行うか。ここで何かが欠けているに違いない。

実際には、.serialize()関数を使用して、jQueryでフォームをJSON文字列に変換できます。しかし、なぜ特にjsonを送信する必要があるのですか?フォームデータを送信することの何が問題になっていますか?
Daniel Roseman、

4
生のフォームデータでは不十分な場合が多くあります。JSONでは、key:valueペアだけでなく、階層オブジェクトを送信できます。入れ子になったセットや配列などを送信できます。おそらくすべてをポストデータで実行できますが、それほど便利ではありません。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構文でそれにインデックスを付けるだけです。

フォームフィールドがfredであるとすると、次のようなことができます。

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

または、フォームオブジェクトを使用してPOSTデータを処理します。


何も含まれていないrequest.POST ['json']を探していました。lenは0でした

それから、ダニエルが示唆したように、JavaScript呼び出しを確認することは間違いなく役立ちます。
Vinay Sajip、2009

13
request.POSTは、POSTリクエストの本文がフォームエンコードされている場合にのみ入力されます。それ以外の場合は空です。
slacy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.