我正在使用Django 2.x
和Django 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,因此联系人数据仅包含模型字段,而没有包含定义了其他属性字段。
答案 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()