2016-08-03 15 views
-1

Ich stoße auf ein Problem in Django, wenn ich versuche, eine PUT-Anfrage in Postman zu machen.nicht hashbar Typ: 'OrderedDict'

Ich vermute, das Problem liegt daran, dass ich Serialisierer in meiner Modellklasse verschachtelt habe, aber ich bin mir nicht sicher.

class Foo(models.Model): 
    foo_name = models.CharField(max_length=50, unique=True) 

    foo_statistics = models.ManyToManyField(TrainStatistics) 

class FooSerializer(serializers.ModelSerializer): 
    blah_statistics = BlahStatisticsSerializer(many=True) 

    class Meta: 
     model = Foo 
     fields = ('foo_statistics') 
     depth = 2 

    def create(self, validated_data): 
     """ 
     Create and return a new `Summary` instance, given the validated data. 
     """ 

     blah_statistics_data = validated_data.pop('blah_statistics') 
     foo = Foo(**validated_data) 

     for blah_statistic in blah_statistics_data: 
      FooStatistic.objects.create(summary=summary, **train_statistic) 
     return summary 

    def update(self, instance, validated_data): 
     """ 
     Update and return an existing `Foo` instance, given the validated data. 
     """ 
     instance.blah_statistics = validated_data.get('blah_statistics', instance.blah_statistics) # This line is causing problems 

Jede Idee, was könnte dieses Problem verursachen?

+0

auf den Grund gehen und die Spur hinterlassen, wo der Fehler im Code auftritt. – levi

+1

Kopieren oder verknüpfen Sie niemals ein Bild für den Fehler, fügen Sie das vollständige Traceback ein. –

+0

Aktualisiert die Frage mit der Zeile, die unten Probleme verursacht –

Antwort

2

Das Problem ist, dass die validierten Daten schaltet train_statistics in ein OrderedDict (immer ist es ein bisschen schwierig mit verschachtelten Serializer arbeiten), so OrderedDicts unhashable sind, so dass, wenn Sie versuchen, „.get“, um es löst einen Fehler.

Eine Option ist, Ihr Feld train_statistics in schreibgeschützt zu setzen.

Dann in Ihrer update() Methode, statt validated_data die Verwendung train_statistics zu erhalten, verwenden Sie request.data für sie zu bekommen. Machen Sie dasselbe für create() Methode.

class SummarySerializer(serializers.ModelSerializer): 
    train_statistics = TrainStatisticsSerializer(many=True, read_only=True) 

    class Meta: 
     model = Summary 
     fields = ('train_statistics') 
     depth = 2 

    def create(self, validated_data): 
     """ 
     Create and return a new `Summary` instance, given the validated data. 
     """ 
     request = self.context['request'] 
     train_statistics_data = request.data.get('train_statistics') 
     summary = Summary.objects.create(**validated_data) 

     for train_statistic in train_statistics_data: 
      TrainStatistics.objects.create(summary=summary, **train_statistic) 
     return summary 

    def update(self, instance, validated_data): 
     """ 
     Update and return an existing `Summary` instance, given the validated data. 
     """ 
     request = self.context['request'] 
     instance.train_statistics =request.data.get('train_statistics', instance.train_statistics) # This line is causing problems 

Wenn Sie Ihren Serializer rufen, müssen Sie Request-Objekt als Kontextdaten zu übergeben.

SummarySerializer(instance, data=data, context={'request':request}) 

oder

SummarySerializer(data=data, context={'request':request}) 
+0

danke für die Antwort. Ich fügte Ihre Änderungen hinzu und es sagt, dass mein 'SummarySerializer' Objekt keine Attribut 'Anfrage' in der Update-Methode hat. Muss ich dies als Parameter in der Update-Methode übergeben? –

+0

@MatthewLin Sorry, ich habe es vergessen, du musst es weitergeben, ich habe meine Antwort aktualisiert. – levi