在使用Django和Angular的過程當中,遇到過一個Angular向Django POST數據的問題。django
// Angular $http({ url: "myviews", method: "POST", data: {'text': 'hello world', 'date': '2017-01-04'} })
# Django def myviews(request): print request.POST print request.body
以上將會打印出json
<QueryDict: {}> u"{'text': 'hello world', 'date': '2017-01-04'}"
而咱們指望是這樣的結果app
<QueryDict: {u'text': u'hello world', u'date': u'2017-01-04'}> u"{'text': 'hello world', 'date': '2017-01-04'}"
出現這種問題是由於Angular默認發送的數據格式是JSON
而不是urlencode
,而Django的request.POST
沒法解析JSON
,因此纔會出現上面的結果。函數
解決的辦法有不少,最簡單粗暴的辦法就是在每一個視圖函數裏面都將request.body
進行解析url
def myviews(request): data = urlencode(json.loads(request.body)) q_data = QueryDict(data)
咱們能夠把這類操做提取出來,寫成Middlerware
,在request
請求到達視圖函數以前就給統一處理好code
class JSONMiddleware(object): """ Process application/json requests data from GET and POST requests. """ def process_request(self, request): if 'application/json' in request.META['CONTENT_TYPE']: data = json.loads(request.body) q_data = QueryDict('', mutable=True) for key, value in data.iteritems(): if isinstance(value, list): for x in value: q_data.update({key: x}) else: q_data.update({key: value}) if request.method == 'GET': request.GET = q_data if request.method == 'POST': request.POST = q_data return None
由於有的request
請求當中沒有CONTENT-TYPE
這個Header
,因此咱們須要判斷一下,之因此不簡單的轉化成Dict
而是QueryDict
是由於遵循一致性的原則,咱們想要將結果綁定在request.GET
或者request.POST
上面,而它們都是QueryDict
類型。QueryDict
和Dict
最大的區別是QueryDict
將每一個value
存在列表當中,而且QueryDict
是不可修改類型。因此當value
是列表時咱們也必須作一下判斷,不然整個列表將做爲一個元素存入QueryDict
的列表當中。ip
a = {"a": [123, 456, 444], "b": 456} # 不作判斷 data = QueryDict('', mutable=True) for k, v in a.iteritems(): data.update({k: v}) print data # 作判斷 data = QueryDict('' mutable=True) for k, v in a.iteritems(): if isinstance(v, list): for x in value: data.update({k: x}) else: data.update({k: v}) print data
<QueryDict: {u'a': [[123, 456, 444]], u'b': [456]}> <QueryDict: {u'a': [123, 456, 444], u'b': [456]}>