【问题标题】:unhashable type: 'OrderedDict'不可散列的类型:'OrderedDict'
【发布时间】:2016-12-09 18:51:57
【问题描述】:

当我尝试在 Postman 中执行 PUT 请求时,我在 Django 中遇到问题。

我怀疑这个问题是因为我的模型类中有嵌套的序列化程序,但我不确定。

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

知道是什么导致了这个问题吗?

【问题讨论】:

  • 深入了解并发布代码中出现错误的跟踪。
  • 永远不要复制或链接错误的图像,粘贴完整的回溯。
  • 用导致问题底部的行更新了问题
  • @MatthewLin 你能在错误之前发布验证数据的值吗?我认为问题在于 train_statistics 是一个有序的字典,而有序的字典不是哈希值。

标签: django django-rest-framework ordereddictionary


【解决方案1】:

问题是经过验证的数据将train_statistics 转换为OrderedDict(使用嵌套序列化程序总是有点棘手),所以OrderedDicts 是不可散列的,所以当你尝试“.get”时它会引发一个错误。

一个选项是将您的字段train_statistics 设置为只读。

然后在您的update() 方法中,不要使用validated_data 获取train_statistics,而是使用request.data 获取它们。对create() 方法执行相同操作。

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

当您调用序列化程序时,您需要将请求对象作为上下文数据传递。

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

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

【讨论】:

  • 感谢您的回答。我添加了您的更改,它说我的“SummarySerializer”对象在更新方法中没有属性“请求”。我是否必须在更新方法中将其作为参数传递?
  • @MatthewLin 对不起,我忘记了,你需要通过它,我更新了我的答案。
  • 在这种情况下,您将提交 train_statistics 数据而不对其进行验证。似乎不是最安全的工作。
猜你喜欢
  • 2013-03-30
  • 1970-01-01
  • 2015-07-05
  • 2017-07-11
  • 2016-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多