英文:
Update database partially by patch, django rest framework
问题
Here is the translated code portion:
我有我的 `CustomUser` 模型,它扩展了 `AbstractUser`
```python
class CustomUser(AbstractUser):
detail = models.JSONField(default=dict)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
然后,现在我只想更新 detail
列。
在 JavaScript 中,通过以下方式进行补丁请求。
var formData = new FormData();
var status = {
fileObj:this.fileObj.id
}
console.log("syncdata to user table",status);
console.log("syncdata for user:",request);
formData.append("detail",JSON.stringify(status));
axios.patch(
`/api/customusers/3/`,formData,{
}
).then(function (response) {
console.log("syncdata customuser is saved:",response);
})
.catch(function (response) {
console.log("syncdata customuser failed:",response);
});
这将通过 <QueryDict: {'detail': ['{"fileObj":19}']}>
作为 request.data
。
在 views.py
中:
class CustomUserViewSet(viewsets.ModelViewSet):
serializer_class = s.CustomUserSerializer
queryset = m.CustomUser.objects.all()
def update(self,request,*args,**kwargs):
print("custom user update")
print(request.data) // <QueryDict: {'detail': ['{"fileObj":19}']}>
instance = self.get_object()
serializer = self.get_serializer(instance,data = request.data)
if serializer.is_valid():
self.perform_update(serializer)
return Response(serializer.data)
else:
print(serializer.errors) // check error.
然而,serializer
返回错误:
{'username': [ErrorDetail(string='This field is required.', code='required')]}
我想要做的只是更新 detail
字段,但它要求 username
。我错在哪里?
<details>
<summary>英文:</summary>
I have my `CustomUser` model which extend `AbstractUser`
class CustomUser(AbstractUser):
detail = models.JSONField(default=dict)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
pass
then now I want to update only `detail` column.
in javascript through patch request like this below.
var formData = new FormData();
var status = {
fileObj:this.fileObj.id
}
console.log("syncdata to user table",status);
console.log("syncdata for user:",request);
formData.append("detail",JSON.stringify(status));
axios.patch(
`/api/customusers/3/`,formData,{
}
).then(function (response) {
console.log("syncdata customuser is saved:",response);
})
.catch(function (response) {
console.log("syncdata customuser failed:",response);
});
this through `<QueryDict: {'detail': ['{"fileObj":19}']}>` as `request.data`
in views.py
class CustomUserViewSet(viewsets.ModelViewSet):
serializer_class = s.CustomUserSerializer
queryset = m.CustomUser.objects.all()
def update(self,request,*args,**kwargs):
print("custom user update")
print(request.data) // <QueryDict: {'detail': ['{"fileObj":19}']}>
instance = self.get_object()
serializer = self.get_serializer(instance,data = request.data)
if serializer.is_valid():
self.perform_update(serializer)
return Response(serializer.data)
else:
print(serializer.errors) // check error.
However `serializer` returns the error,
{'username': [ErrorDetail(string='This field is required.', code='required')]}
What I want to do is just update the `detail` field only, but it require the `username`.
Where am I wrong?
</details>
# 答案1
**得分**: 1
```python
这是实现在ModelViewSet中进行更新和部分更新的Mixin类。
在接收到HTTP `PATCH` 方法请求时,DRF会调用你的 `partial_update` 方法。然后在 `update` 方法中,`serializer = self.get_serializer(instance, data=request.data, partial=partial)` 通过 `partial` 参数来判断是否进行部分更新。所以要解决你的问题,你只需要重新编写你的 `update` 方法如下:
```python
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
print("自定义用户更新")
print(request.data) # <QueryDict: {'detail': ['{"fileObj":19}']}>
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
if serializer.is_valid():
self.perform_update(serializer)
return Response(serializer.data)
else:
print(serializer.errors) # 检查错误
<details>
<summary>英文:</summary>
This is the Mixin class that implements update and partial update in ModelViewSet.
```python
class UpdateModelMixin:
"""
Update a model instance.
"""
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return Response(serializer.data)
def perform_update(self, serializer):
serializer.save()
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
When receiving HTTP PATCH
method request, DRF will call your partial_update
method.Then the serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer in the update
method judges whether it is a partial update through the partial
parameter. So to solve your problem, you just need to rewrite your update
method as:
def update(self,request,*args,**kwargs):
partial = kwargs.pop('partial', False)
print("custom user update")
print(request.data) // <QueryDict: {'detail': ['{"fileObj":19}']}>
instance = self.get_object()
serializer = self.get_serializer(instance,data = request.data, partial=partial)
if serializer.is_valid():
self.perform_update(serializer)
return Response(serializer.data)
else:
print(serializer.errors) // check error.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论