![](/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.