【问题标题】:'collections.OrderedDict' object has no attribute 'pk' - django rest framework'collections.OrderedDict' 对象没有属性 'pk' - django rest 框架
【发布时间】:2018-03-30 01:28:04
【问题描述】:

我有一个模型,我想为它写一个update() 方法以便更新。 下面的 sn-p 是我的模型:

class Klass(models.Model):
    title = models.CharField(max_length=50)
    description = models.CharField(max_length=500)
    university = models.CharField(max_length=50,blank=True, null=True)
    teacher = models.ForeignKey(Profile, related_name='teacher', on_delete=models.CASCADE)

下面的sn-p对应Serializer:

class KlassSerializer(ModelSerializer):
        teacher = ProfileSerializer()
        url = HyperlinkedIdentityField(view_name='mainp-api:detail', lookup_field='pk')
        klass_settings = KlassSettingsSerializer()

    class Meta:
        model = Klass
        fields = ('url', 'id', 'title', 'description', 'university','teacher')

    
    def update(self, instance, validated_data):
        instance.title = validated_data.get('title', instance.title)
        instance.description = validated_data.get('description', instance.description)
        instance.university = validated_data.get('university', instance.university)
        instance.save()

        return instance

为了更新,我使用下面的 sn-p:

class KlassAPIView(APIView):    
    def put(self, request, pk=None):
        if pk == None:
            return Response({'message': 'You must specify class ID'}, status=HTTP_400_BAD_REQUEST)

        klass = Klass.objects.get(pk=pk)
        if request.user.profile.type != 't':
            raise PermissionDenied(detail={'message': 'You aren't teacher of this class, so you can't edit information.'})

        serializer = KlassSerializer(data=request.data, context={'request': request})
        serializer.initial_data['teacher'] = request.user.profile.__dict__

        if serializer.is_valid():
            serializer.update(instance=klass, validated_data=serializer.data)  # Retrieve teacher and store
            return Response({'data': serializer.data}, status=HTTP_200_OK)
        else:
            return Response({'data': serializer.errors}, status=HTTP_400_BAD_REQUEST)

但是当我使用PUT 方法发送数据时,它返回以下错误:

/api/class/49/处的AttributeError

'collections.OrderedDict' 对象没有属性 'pk'

并且错误发生在serializer.update(instance=klass, validated_data=serializer.data) 行。

【问题讨论】:

  • 不清楚你在这里做什么。为什么要将序列化程序的数据传回自身?
  • 您不应明确调用update()。你应该打电话给save()
  • 另外,你也不需要定义update;另外,与表单一样,如果您传递显式数据,initial_data 将被忽略。这都是错误的。
  • @JahongirRahmonov 如果我调用 save(),它会在数据库中创建一个新对象和一个新行。我声明了create() 方法,似乎create() 将被调用。
  • @msln 确保您在 PUT 的数据中包含 id。然后,它将尝试更新,而不是创建。如果没有id,当然会尝试创建一个。

标签: python django django-models django-rest-framework django-rest-viewsets


【解决方案1】:

刚刚遇到同样的错误。

就我而言,问题是我在访问 serializer.data 之前访问了 serializer.save()

Google 把我丢到这里了,所以也许其他人也会觉得这很有帮助。

来源:https://github.com/encode/django-rest-framework/issues/2964

【讨论】:

  • 这对我有用。在 DRF 中,当基于模型的序列化程序时, save() 确保所有更改都保存到数据库中:django-rest-framework.org/api-guide/serializers/… 看起来如果不将序列化程序保存到数据库,就无法访​​问序列化程序中的列表,这很奇怪......任何人都知道为什么?
  • 不保存到数据库的解决方法是访问 serializer.validated_data
【解决方案2】:

我不知道这是否有帮助。由于类似的问题,我总是在序列化程序中添加id 字段:

id = serializers.ModelField(model_field=YourModel._meta.get_field('id'), required=False)

确保它是 required=False,因为当您创建新记录时,id 字段不存在。

【讨论】:

    【解决方案3】:

    在我的情况下,我正在做:

    champions_list = []
    
    for champion in champions_serializer.data:
       c = {"id": champion.id}
       champions_list.append(c)
    

    而正确的做法是:

    champions_list = []
    
    for champion in champions_serializer.data:
       c = {"id": champion["id"]}
       champions_list.append(c)
    

    并确保在序列化程序中返回 id。

    【讨论】:

    • 我刚刚遇到了同样的问题并通过不使用点表示法解决了它。
    【解决方案4】:

    此问题的许多答案都指出,必须在使用 serializer.data 之前调用 serializer.save()

    就我而言,我肯定调用了serializer.save(),但是,我在我的序列化程序上覆盖了save 方法,并且没有在该方法的序列化程序上设置self.instance

    因此,如果您要覆盖 save,请务必这样做:

    class MySerializer(serializers.ModelSerializer):
        def save(self, *args, **kwargs):
            ...
            self.instance = instance
            return self.instance
    

    【讨论】:

      猜你喜欢
      • 2015-07-14
      • 2021-05-02
      • 1970-01-01
      • 2017-06-17
      • 2017-08-11
      • 2016-06-30
      • 2021-02-04
      • 2021-04-28
      • 1970-01-01
      相关资源
      最近更新 更多