2016-02-17 81 views
5

我試圖創建一個可寫嵌套序列化程序。我的父母模型是遊戲,嵌套模型是測量。我正嘗試使用AJAX將這些數據發佈到我的DRF應用程序。但是,嘗試發佈數據時,嵌套的度量值爲空OrderedDict()。Django Rest Framework具有多個嵌套對象的可寫嵌套序列化程序

這裏是我的模型:

class Game(models.Model): 
    start_timestamp = models.DateTimeField(auto_now_add=False) 
    end_timestamp = models.DateTimeField(auto_now_add=False) 
    date_added = models.DateTimeField(auto_now_add=True) 


class Measurement(models.Model): 
    game = models.ForeignKey(Game, on_delete=models.PROTECT, related_name='measurements') 
    measurement_type = models.CharField(max_length=56) 
    measurement = models.CharField(max_length=56) 
    timestamp = models.DateTimeField(auto_now_add=False) 
    date_added = models.DateTimeField(auto_now_add=True) 

這裏是我的串行:

class MeasurementSerializer(serializers.ModelSerializer): 
     timestamp = serializers.DateTimeField(input_formats=(['%Y-%m-%d %H:%M:%S.%Z', 'iso-8601']), required=False) 

     class Meta: 
      model = Measurement 
      fields = ('measurement_type', 'measurement', 'timestamp') 


class GameSerializer(serializers.ModelSerializer): 
    start_timestamp = serializers.DateTimeField(input_formats=(['%Y-%m-%d %H:%M:%S.%Z', 'iso-8601'])) 
    end_timestamp = serializers.DateTimeField(input_formats=(['%Y-%m-%d %H:%M:%S.%Z', 'iso-8601'])) 
    measurements = MeasurementSerializer(many=True) 

    class Meta: 
     model = Game 
     fields = ('id', 'start_timestamp', 'end_timestamp', 'measurements') 

    def create(self, validated_data): 
     measurements = validated_data.pop('measurements') 
     game = Game.objects.create(**validated_data) 
     for measurement in measurements: 
      Measurement.objects.create(game=game, **measurement) 
     return game 

我對遊戲的看法是如下:

class GameList(generics.ListCreateAPIView): 
    queryset = Game.objects.all() 
    serializer_class = GameSerializer 

我跟着this tutorial的結構。

我試圖通過AJAX張貼到這個API,代碼如下:

$.ajax({ 
     url: base_url + '/games/', 
     dataType: "json", 
     data: { 
       "start_timestamp": "2016-02-16 14:51:43.000000", 
       "end_timestamp": "2016-02-16 14:53:43.000000", 
       "measurements":[ 
        {'measurement_type':'type1', 'measurement':'71', 'timestamp':'2016-02-16 14:53:43.000000'}, 
        {'measurement_type':'type1', 'measurement':'72', 'timestamp':'2016-02-16 14:54:43.000000'}, 
        {'measurement_type':'type1', 'measurement':'73', 'timestamp':'2016-02-16 14:55:43.000000'}, 
       ] 
       }, 
     type: 'POST' 
    }) 
    .error(function(r){}) 
    .success(function(data){}) 
}); 

在發佈這個數據,我發現在GameSerializer內的創建方法是,validate_data.pop(「三圍」)包含空的3個有序詞典(OrderedDict())的列表。

更新:我已經發現,通過request.data未來在initial_data的結構,像這樣:

'emotion_measurements[0][measurement_type]' (4397175560) = {list} ['type1'] 
'emotion_measurements[0][measurement]' (4397285512) = {list} ['71'] 
'emotion_measurements[0][timestamp]' (4397285600) = {list} ['2016-02-16 14:53:43.000000'] 
'emotion_measurements[1][measurement_type]' (4397175040) = {list} ['type1'] 
'emotion_measurements[1][measurement]' (4397285864) = {list} ['72'] 
'emotion_measurements[1][timestamp]' (4397285952) = {list} ['2016-02-16 14:54:43.000000'] 
'emotion_measurements[2][measurement_type]' (4397175040) = {list} ['type1'] 
'emotion_measurements[2][measurement]' (4397285864) = {list} ['73'] 
'emotion_measurements[2][timestamp]' (4397285952) = {list} ['2016-02-16 14:55:43.000000'] 

有沒有人遇到過這個問題?謝謝!

更新#2

我能解決這個(雖然我認爲它更是一個解決辦法比溶液)中加入以下我MeasurementSerializer:

def to_internal_value(self, data): 
     formatted_data = json.dumps(data) 
     formatted_data = formatted_data.replace("[", "").replace("]","") 
     formatted_data = json.loads(formatted_data) 
     return formatted_data 

的測量數據來在我相信我需要一個字典時,它是一個QueryDict。關鍵和值還有一些額外的括號,所以我不得不刪除這些。

仍在尋找比這更好的答案!

+1

你可以檢查'self.initial_data.get('measurements')'中有什麼?另外,爲了安全起見,請檢查您的服務器收到的是哪個JSON。 (你的AJAX代碼看起來不錯,它肯定會到達服務器,就像預期的那樣 - 但是...) – Risadinha

+0

我查找了幾次代碼後,唯一想到的就是可能(也許!)你的時間戳無法解析到你的模式。我找不到其他任何東西,比較我自己的序列化程序和DRF示例。由於時間戳是可選的,因此可以在沒有這些值的情況下進行測試,只是爲了確保。但是,如果這是問題,那麼問題就是爲什麼你沒有看到驗證錯誤。 – Risadinha

+0

@Risadinha我已經更新了initial_data結構。該結構是一個QueryDict,我不太熟悉。 我也有相同的思路做時間戳不需要的情況下,它是一個日期時間格式問題,但仍然是同樣的問題。 –

回答

0

這裏的問題在前端。默認情況下,服務器會把數據application/x-www-form-urlencoded,爲了讓它知道,您正在向它發送json,你需要在你$.ajax請求指定contentType

$.ajax({ 
    url: base_url + '/games/', 
    dataType: "json", 
    data: {...}, 
    contentType: 'application/json; charset=UTF-8', // add this line 
    type: 'POST' 
}) 
.error(function(r){}) 
.success(function(data){}); 

現在你在create()方法validated_data.pop('measurements')GameSerializer應該產生三個對象與您的measurements(但不要忘記從更新#2重做您的解決方法)。

相關問題