无效数据。需要字典,但在 Django Rest Framework 中使用序列化器字段出现 str 错误

Anu*_*TBE 9 django django-serializer 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)
Run Code Online (Sandbox Code Playgroud)

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'
        )
Run Code Online (Sandbox Code Playgroud)

视图.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)
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

它给出了错误

{"contact":{"non_field_errors":["Invalid data. Expected a dictionary, but got str."]}}
Run Code Online (Sandbox Code Playgroud)

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

sli*_*der 8

我不是这种请求解析模式的忠实粉丝。据我了解,您希望能够在检索AmountGiven对象时查看所有联系人的详细信息,同时AmountGiven只需提供联系人 ID即可创建和更新。

因此,您可以将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'
        )
Run Code Online (Sandbox Code Playgroud)

请注意,该contact_detail字段有一个source属性。

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

当您检索一个AmountGiven对象时,您应该获得该contact_detail字段中联系人的所有详细信息。

更新

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

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()
Run Code Online (Sandbox Code Playgroud)