无效数据。需要一个字典,但 Django Rest Framework 中的序列化程序字段出现 str 错误

Invalid data. Expected a dictionary, but got str error with serializer field in Django Rest Framework

我正在使用 Django 2.xDjango REST Framework

我有两个模型像

class Contact(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey(User, on_delete=models.PROTECT)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100, blank=True, null=True)
    modified = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)

class AmountGiven(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    contact = models.ForeignKey(Contact, on_delete=models.PROTECT)
    amount = models.FloatField(help_text='Amount given to the contact')
    given_date = models.DateField(default=timezone.now)
    created = models.DateTimeField(auto_now=True)

serializer.py 文件的序列化器定义为

class ContactSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Contact
        fields = ('id', 'first_name', 'last_name', 'created', 'modified')

class AmountGivenSerializer(serializers.ModelSerializer):
    contact = ContactSerializer()

    class Meta:
        model = AmountGiven
        depth = 1
        fields = (
            'id', 'contact', 'amount', 'given_date', 'created'
        )

views.py

class AmountGivenViewSet(viewsets.ModelViewSet):
    serializer_class = AmountGivenSerializer

    def perform_create(self, serializer):
        save_data = {}
        contact_pk = self.request.data.get('contact', None)
        if not contact_pk:
            raise ValidationError({'contact': ['Contact is required']})
        contact = Contact.objects.filter(
            user=self.request.user,
            pk=contact_pk
        ).first()
        if not contact:
            raise ValidationError({'contact': ['Contact does not exists']})
        save_data['contact'] = contact
        serializer.save(**save_data)

但是当我向 AmountGiven 模型添加一条新记录并在 contact 字段中传递 contact id 时

它给出的错误是

{"contact":{"non_field_errors":["Invalid data. Expected a dictionary, but got str."]}}

当我从 AmountGivenSerializer 中删除 contact = ContactSerializer() 时,它按预期工作正常,但随后响应 depth 设置为 1,联系人数据包含仅模型字段,未定义其他 属性 字段。

覆盖AmountGivenSerializer__init__()方法为

class AmountGivenSerializer(serializers.ModelSerializer):
    <b>def __init__(self, *args, **kwargs):
        super(AmountGivenSerializer, self).__init__(*args, **kwargs)
        if 'view' in self.context and self.context['view'].action != 'create':
            self.fields.update({"contact": ContactSerializer()})</b>

    class Meta:
        model = AmountGiven
        depth = 1
        fields = (
            'id', 'contact', 'amount', 'given_date', 'created'
        )


描述
问题是 DRF 期望来自 contact 字段的类似字典的对象,因为您定义了 nested serializer。因此,我借助重写 __init__() 方法

动态删除了 嵌套关系

我不太喜欢这种请求解析模式。据我了解,您希望在检索 AmountGiven 对象时能够看到所有联系人的详细信息,同时能够通过提供联系人 ID 来创建和更新 AmountGiven

因此,您可以将 AmountGiven 序列化器更改为 contact 模型字段有 2 个字段。像这样:

class AmountGivenSerializer(serializers.ModelSerializer):
    contact_detail = ContactSerializer(source='contact', read_only=True)

    class Meta:
        model = AmountGiven
        depth = 1
        fields = (
            'id', 'contact', 'contact_detail', 'amount', 'given_date', 'created'
        )

请注意,contact_detail 字段具有 source 属性。

现在,创建和更新的默认功能应该开箱即用(验证和一切)。

并且当您检索 AmountGiven 对象时,您应该在 contact_detail 字段中获取联系人的所有详细信息。

更新

我错过了您需要检查 Contact 是否属于某个用户(但是,我在您的 Contact 模型上没有看到 user 字段,也许您错过了发布它)。您可以简化该检查:

class AmountGivenViewSet(viewsets.ModelViewSet):
    serializer_class = AmountGivenSerializer

    def perform_create(self, serializer):
        contact = serializer.validated_data.get('contact')
        if contact.user != self.request.user:
            raise ValidationError({'contact': ['Not a valid contact']})
        serializer.save()