2016-11-16 136 views
0

我很想弄清楚如何在DRF中編寫自定義串行器來解析傳遞給端點的複雜JSON數據結構。該JSON看起來是這樣的:Django Rest框架:自定義JSON串行器

{ 
    "name": "new", 
    "site": "US", 
    "data": { 
     "settings": [], 
     "meta": { 
      "meta1":{} 
     } 
    } 
} 

這裏是我的後端代碼:

# views.py 
class SaveData(views.APIView): 
    def post(self, request, *args, **kwargs): 
     name = request.POST.get('name') 
     site = request.POST.get('site') 
     data = request.POST.get('data') 

data總是返回None。在仔細檢查進入request對象,傳入的JSON看起來是這樣的:

# POST attribute of request object 
'name' = 'new' 
'site' = 'US' 
'data[settings][0] = '' 
'data[meta][meta1][] = '' 

基本上它看起來與data鍵關聯的嵌套JSON對象未能恰當序列化爲Python的dictlist對象。我一直在尋找自定義DRF序列化器的例子,但是我發現的大多數序列化器都是用來序列化Django模型的,但我不需要那樣做。傳入的數據不會直接映射到我的模型;相反,我需要在保存任何數據之前進行一些處理。

有沒有人對自定義序列化程序有任何建議,將正確地將data JSON轉換爲適當的Python對象?我從這開始,但它引發了一個例外(When a serializer is passed a 'data' keyword argument you must call '.is_valid()' before attempting to access the serialized '.data' representation. You should either call '.is_valid()' first, or access '.initial_data' instead.)。這裏是我創建自定義序列化程序的代碼:

# serializers.py 
class SaveDataSerializer(serializers.Serializer): 
    name = serializers.CharField() 
    site = serializers.CharField() 
    data = serializers.DictField() 

    def create(self, validated_data): 
     return dict(**validated_data) 

謝謝。

回答

0

我能夠通過將JS對象傳遞給$.ajax來解決我的問題,然後DRF能夠正確解析爲Python對象。下面是jQuery的一個片段我使用:

$.ajax({ 
    url: '/api/endpoint', 
    type: 'POST', 
    contentType: 'application/json', 
    data: JSON.stringify(ajaxData), 
    done: function(data) {} 
    ... 
}) 

不過,請注意jQuery將默認爲x-www-urlencodedContent-Type,如果你不指定任何東西。由於我正在使用JSON.stringify()方法將ajaxData對象顯式轉換爲JSON字符串,因此還需要明確設置Content-Type

我從這個想法SO回答:Convert Object to JSON string

當然,這並沒有真正回答我原來的問題,但這是另一種解決方案是簡單,就像我想要的。通過這樣做,我沒有創建任何自定義序列,但我沒有要修改我的API視圖像這樣:

class SaveData(views.APIView): 
    def post(self, request, *args, **kwargs): 
     name = request.data.get('name') 
     site = request.data.get('site') 
     data = request.data.get('data') 

這樣預期的對象類型返回

>>> type(name) 
str 
>>> type(site) 
str 
>>> type(data) 
dict