![](/img/trans.png)
[英]How to provide additional data in “PUT” request for update in Django REST Framework?
[英]Django Rest Framework (DRF) Refuses to Validate Data with Foreign Keys in Update (PUT) Request
使用 Django REST Framework (DRF),我试图遵循此链接提供的嵌套序列化程序的 DRF 文档。 目前,让我们假设我的代码如下所示:
模型.py
class PvlEntry(models.Model):
pvl_project = models.OneToOneField("review.ProjectList", on_delete=models.CASCADE, related_name='pvl_project')
pvl_reviewer = models.ForeignKey('auth.User', on_delete=models.CASCADE, related_name='+')
pvl_worktype_is_correct = models.BooleanField(blank=False, null=False)
pvl_hw_description = models.TextField(blank=False, null=False)
class ProjectList(models.Model):
"""
"""
project_number = models.IntegerField(blank=False, null=False, unique=True)
project_manager = models.CharField(blank=False, max_length=255, null=False)
project_name = models.CharField(blank=False,
max_length=255,
null=False)
project_description = models.CharField(blank=True,
max_length=1024,
null=True)
视图.py
class PvlEntryListCreateAPIView(ListCreateAPIView):
""" This view is leveraged for jsGrid so that we can have jsGrid produce
a JavaScript enabled view for actions like editing and filtering of
the project vetting list.
"""
queryset = PvlEntry.objects.all()
serializer_class = PvlEntrySerializer
name = 'listcreate-pvlentry'
def get_queryset(self):
qs = self.queryset.all()
return qs
class PvlEntryRetrieveUpdateDestroyAPIView(RetrieveUpdateDestroyAPIView):
""" Leveraged for jsGrid
"""
queryset = PvlEntry.objects.all()
serializer_class = PvlEntrySerializer
name = 'rud-pvlentry'
序列化程序.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = [
'id',
'first_name',
'last_name',
'email'
]
class ProjectListSerializer(serializers.ModelSerializer):
class Meta:
model = ProjectList
fields = '__all__'
class PvlEntrySerializer(serializers.ModelSerializer):
pvl_project = ProjectListSerializer()
pvl_reviewer = UserSerializer()
def update(self, instance, validated_data):
print(validated_data)
return super(PvlEntrySerializer, self).update(self, instance, validated_data)
class Meta:
model = PvlEntry
fields = '__all__'
现在,我明白,由于这段代码现在位于,它不是一个可写的序列化程序。 但是,有了上面的代码,我不应该至少通过序列化程序对数据的验证吗?
使用 DRF 可浏览 API,当我尝试使用 RetriveUpdateDestroy 内置 API 视图的 PUT 操作时,我收到类似于以下内容的错误:
PUT /pvl/grid/11
HTTP 400 Bad Request
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"pvl_project": {
"project_number": [
"pvl entry with this project number already exists."
]
}
}
同样,我明白我不能像现在这样使用代码执行更新 (PUT),但它至少不应该通过序列化/验证阶段吗? 我也不会创建新记录。 我只是尝试执行更新。 那么,为什么要验证“具有此项目编号的 pvl 条目”是否已经存在?
stackoverflow 上有很多帖子涉及或围绕这个问题跳舞,但由于某种原因,我无法依靠其中任何一个来解决问题。
我也尝试返回并用PrimaryKeyRelatedFields
替换嵌套的序列化程序,但该方法不返回相关数据,只返回对相关数据的引用。
我还尝试了单独的序列化程序,但这种方法对我实现的用于使用模板中的数据的 jsGrid JavaScript 效果不佳。
肯定有一个简单的解决方案吗?
第一个解决方案是您可以使用PATCH
方法而不是PUT
并且不要在表单/ajax 数据中发送pvl_project
(记住设置所需的属性,如pvl_project = ProjectListSerializer(required=False)
。
问题是在 drf PUT
请求方法中尝试将给定实例中的所有提供的数据替换为一个 - 这意味着它将首先分析没有PvlEntry.pvl_project
属性重复,因为它的OneToOneField
。
另一方面, PATCH
可以partialy
更新数据(你可以分析这个问题),你甚至不关心required=False
序列化器属性,因为它只会更新请求中提供的数据(如何通过PUT
方法更新部分在我的最后一个注释)。
第二
现在,当我们解决了第一个概念时,我们可以继续让这个序列化程序工作。 假设您在每个模型上都设置了uuid属性(使用id
字段不是最佳实践),并且您希望通过给定的uuid
属性值设置pvl_project
。
您可以覆盖ProjectListSerializer
中的to_internal_value
方法,该方法用于保存实例并通过给定数据简单地搜索给定对象。
class ProjectListSerializer(serializers.ModelSerializer):
class Meta:
model = ProjectList
fields = '__all__'
def to_internal_value(self, data):
# you can validate data here for sure that provided data is correct uuid string
try:
return ProjectList.objects.get(uuid=data)
except ProjectList.DoesNotExist:
raise ValidationError(['Project list with the given uuid does not exist'])
这个序列化器现在就像一个很好的弹性切换 json <-> api <-> django 模型实例世界。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.