2016-02-17 12 views
5

Sto provando a creare un serializzatore nidificato scrivibile. Il mio modello genitore è Game e i modelli annidati sono Measurements. Sto cercando di inviare questi dati alla mia applicazione DRF usando AJAX. Tuttavia, quando provi a pubblicare i dati, le misure nidificate sono vuote OrderedDict().Django Rest Framework serial nid scrivibile con più oggetti nidificati

Qui sono i miei modelli:

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) 

Ecco le mie serializzatori:

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 

mio punto di vista per il gioco è la seguente:

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

ho seguito this tutorial per la struttura.

Sto cercando di inviare a questa API tramite la tecnologia AJAX, il codice qui sotto:

$.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){}) 
}); 

Su questo distacco dei dati, trovo nel metodo creare all'interno del GameSerializer che il validate_data.pop ('misure') contiene un elenco di 3 dizionari ordinati (OrderedDict()) vuoti.

UPDATE: ho trovato che che le initial_data provenienti in via request.data è strutturato in questo modo:

'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'] 

Qualcuno ha incontrato questo problema prima? Grazie!

UPDATE # 2

ero in grado di risolvere questo (anche se credo che è più di una soluzione che una soluzione) aggiungendo il seguente al mio 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 

i dati di misura provenienti era un QueryDict quando credevo di aver bisogno di un Dict. C'erano anche alcune parentesi aggiuntive attorno alla chiave e ai valori, quindi ho dovuto rimuovere anche quelle.

Ancora in cerca di una risposta migliore di questo!

+1

Potresti controllare cosa c'è in 'self.initial_data.get ('misure')'? E anche, solo per essere al sicuro: controlla cosa ha ricevuto il tuo server JSON. (Il tuo codice AJAX sembra buono e raggiunge sicuramente il server esattamente come previsto - ma beh ...) – Risadinha

+0

L'unico pensiero che riesco a trovare dopo aver controllato il tuo codice più volte è che forse (forse!) Il tuo timestamp non riesce ad analizzare secondo al tuo schema. Non riesco a trovare nient'altro, anche confrontandolo con i miei serializzatori e con l'esempio DRF. Dato che il timestamp è opzionale, forse testarlo senza questi valori, solo per essere sicuro.Ma se questo è il problema, la domanda sarebbe perché non vedi gli errori di validazione. – Risadinha

+0

@Risadinha Ho aggiornato con la struttura initial_data. La struttura è un QueryDict, di cui non ho molta familiarità. Ho anche avuto lo stesso treno di istruzioni per la creazione di timestamp non richiesto nel caso in cui si trattasse di un problema di formattazione dell'ora, ma ancora lo stesso problema. –

risposta

0

Il problema qui è sul lato front-end. Per impostazione predefinita, il server interpreta i dati come application/x-www-form-urlencoded e in modo che esso per capire che si sta inviando un json, è necessario specificare il contentType nella richiesta $.ajax:

$.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){}); 

Ora il vostro validated_data.pop('measurements') in create() il metodo della vostra GameSerializer dovrebbe produrre tre oggetti con measurements (ma non dimenticare di ripetere la soluzione alternativa dall'aggiornamento n. 2).

Problemi correlati