teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

追記 2019/03/15 を追加しました。

2019/03/15 11:55

投稿

gh640
gh640

スコア1407

answer CHANGED
@@ -48,4 +48,72 @@
48
48
 
49
49
  コード:
50
50
 
51
- - [django/request.py at 2.1.7 · django/django · GitHub](https://github.com/django/django/blob/2.1.7/django/http/request.py#L321)
51
+ - [django/request.py at 2.1.7 · django/django · GitHub](https://github.com/django/django/blob/2.1.7/django/http/request.py#L321)
52
+
53
+ ### 追記 2019/03/15
54
+
55
+ > `staff_list = json.loads(request.body).get('staff_list', [])` にすると、staff_listの中身が空ではなくなったのですが、JSONDecodeErrorになってしまいます。
56
+ >
57
+ > ...
58
+ >
59
+ > 度々恐縮ですが、アドバイスいただけますと幸いです。。
60
+
61
+ コメントでいただいた追加のご質問に回答します。
62
+
63
+ こちら検索してみたところ、 `jQuery.ajax()` は `data` パラメータが文字列ではない場合に自動的に query string に変換する挙動をするようです。そして、今回の場合のように、 `data` の値が object で、その要素に array または object が含まれる場合には注意が必要とのことです。
64
+
65
+ 以下 jQuery 公式ドキュメントからの引用です(英語に抵抗があれば Google 翻訳等を使ってください)。
66
+
67
+ > data
68
+ >
69
+ > Type: `PlainObject` or `String` or `Array`
70
+ >
71
+ > Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests. See `processData` option to prevent this automatic processing. Object must be Key/Value pairs. If value is an Array, jQuery serializes multiple values with same key based on the value of the `traditional` setting (described below).
72
+
73
+ - [jQuery.ajax() | jQuery API Documentation](http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings)
74
+
75
+ > **Note:** Because some frameworks have limited ability to parse serialized arrays, developers should exercise caution when passing an `obj` argument that contains objects or arrays nested within another array.
76
+ >
77
+ > **Note:** Because there is no universally agreed-upon specification for param strings, it is not possible to encode complex data structures using this method in a manner that works ideally across all languages supporting such input. Use JSON format as an alternative for encoding complex data instead.
78
+
79
+ - [jQuery.param() | jQuery API Documentation](http://api.jquery.com/jQuery.param/)
80
+
81
+ というわけで、フロント側とバックエンド側の両方で少し工夫が必要なようですね。すみません、私は jQuery で試していなかったので気が付きませんでした。
82
+
83
+ というわけで、具体的には、例えば JS 側を次のようにして
84
+
85
+ ```js
86
+ $.ajax({
87
+ 'url': '{% url "myapp:ajax_order_change" %}',
88
+ 'type': 'POST',
89
+ 'data': {
90
+ 'staff_list': JSON.stringify(staff_list),
91
+ },
92
+ 'dataType': 'json'
93
+ });
94
+ });
95
+ ```
96
+
97
+ バックエンド側を次のようにすると値が取得できるのではないかと思います。
98
+
99
+ ```python
100
+ import json
101
+ from django.http import QueryDict
102
+
103
+ def ajax_order_change(request, store_id):
104
+ # print() はデバッグが終われば削除してください
105
+ print(request.body)
106
+ params = QueryDict(request.body)
107
+ print(params)
108
+ staff_list = json.loads(params['order'])
109
+ print(staff_list)
110
+ // ...
111
+ ```
112
+
113
+ `request.body` が query string になって渡されるので `QueryDict` に渡して使うとやりやすいと思います。
114
+
115
+ あくまでもサンプルなので、コピペせずアイデアのみ参考にしてください。また、繰り返しになりますが、どのようなデータが来るかわからないという前提で、例外処理等は適切に行ってくださいね :D
116
+
117
+ この点についてはこれで解決するのではないかと思います。
118
+
119
+ もし他にも問題が出てきましたら、一対一でサポートし続けるのは難しいので、別の質問を立ててみてくださいー

1

追加のご質問を受けて追記 2019/03/14 を追加しました。

2019/03/15 11:55

投稿

gh640
gh640

スコア1407

answer CHANGED
@@ -11,4 +11,41 @@
11
11
 
12
12
  jQuery UI Sortable を使われているのであれば次のページ等が参考になるものと思います。
13
13
 
14
- - [php - jQuery UI Sortable, then write order into a database - Stack Overflow](https://stackoverflow.com/questions/15633341/jquery-ui-sortable-then-write-order-into-a-database)
14
+ - [php - jQuery UI Sortable, then write order into a database - Stack Overflow](https://stackoverflow.com/questions/15633341/jquery-ui-sortable-then-write-order-into-a-database)
15
+
16
+ ### 追記 2019/03/14
17
+
18
+ > フロント側からのデータを取得できない理由を教えていただけますと幸いです。
19
+
20
+ CSRF 設定( `@csrf_exempt` 等)は適切にされていて `ajax_order_change()` が実行されているのに `print(staff_list)` が空になる、ということですかね。
21
+
22
+ 公式ドキュメントを読むと
23
+
24
+ > If you need to access raw or non-form data posted in the request, access this through the HttpRequest.body attribute instead.
25
+
26
+ - [Request and response objects | Django documentation | Django](https://docs.djangoproject.com/en/2.1/ref/request-response/#django.http.HttpRequest.POST)
27
+
28
+ とのことで、このケースでは `request.POST` は使えないようですね。次のような感じで取得する必要があるのだと思います。
29
+
30
+ ```python
31
+ import json
32
+ staff_list = json.loads(request.body).get('staff_list', [])
33
+ ```
34
+
35
+ これ ↑ はあくまでも説明のための単純化したサンプルです。実際にはどのようなデータが来るかわからないという前提で、例外処理等は適切に行ってください。
36
+
37
+ 以下参考です。
38
+
39
+ Stack Overflow の質問:
40
+
41
+ - [Django & TastyPie: request.POST is empty - Stack Overflow](https://stackoverflow.com/questions/16213324/django-tastypie-request-post-is-empty)
42
+
43
+ 公式ドキュメント:
44
+
45
+ > request.POST will no longer include data posted via HTTP requests with non form-specific content-types in the header. In prior versions, data posted with content-types other than multipart/form-data or application/x-www-form-urlencoded would still end up represented in the request.POST attribute. Developers wishing to access the raw POST data for these cases, should use the request.body attribute instead.
46
+
47
+ - [Django 1.5 release notes | Django documentation | Django](https://docs.djangoproject.com/en/2.1/releases/1.5/#non-form-data-in-http-requests)
48
+
49
+ コード:
50
+
51
+ - [django/request.py at 2.1.7 · django/django · GitHub](https://github.com/django/django/blob/2.1.7/django/http/request.py#L321)