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

时间:2018-10-18 06:11:22

标签: django django-rest-framework django-serializer

我正在使用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

enter image description here

它给出错误为

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

当我从 AmountGivenSerializer 中删除contact = ContactSerializer()时,它可以按预期运行,但是由于depth设置为1,因此联系人数据仅包含模型字段,而没有包含定义了其他属性字段。

2 个答案:

答案 0 :(得分:1)

__init__() AmountGivenSerializer 方法覆盖为

class AmountGivenSerializer(serializers.ModelSerializer):
    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()})

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


说明
问题在于,由于您已定义 contact ,因此DRF希望nested serializer字段中提供类似dict的对象。因此,在覆盖__init__()方法的帮助下,我动态删除了 嵌套关系

答案 1 :(得分:1)

我不是这种请求解析模式的忠实拥护者。据我了解,您希望在检索AmountGiven对象时能够查看所有联系人的详细信息,同时能够仅通过提供联系人ID来创建和更新AmountGiven。 / p>

因此,您可以将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是否属于用户的权限(但是,我在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()