django - 使用 RetrieveUpdateAPIView 更新数据 - 从序列化程序获取经过验证的数据
问题描述
我想通过 PUT 请求更新用户的某些属性(比如 first_name 和 last_name)我的 json 对象看起来像这样
{
"user" : {
"first_name": "Jack",
"last_name": "shnider",
"password":"admin123"
"email" : "foo@google.com"
},
"employee_zip" : 12345
}
这就是我的视图(我想将现有字段更新为这些新字段)。
这些是序列化程序
class Serializer_UpdateUser(ModelSerializer):
class Meta:
model = User
fields = ('first_name','last_name','password')
class Serializer_UpdateEmployer(ModelSerializer):
user = Serializer_UpdateUser()
class Meta:
model = modelEmployer
fields = [
'user',
'employer_zip',
]
这是视图:
class UpdateProfile_RetrieveUpdateAPIView(RetrieveUpdateAPIView):
queryset = modelEmployer.objects.all()
serializer_class = Serializer_UpdateEmployer
lookup_field = 'user__email'
permission_classes = [permissions.AllowAny]
def update(self, request, *args, **kwargs):
instance = self.get_object() #------>I have the object that I would like to update
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True) #--->Success
现在我想获得一个经过验证的字段(json 只包含已更新的字段)。我知道如果我做这样的事情
serializer.save
我会取回一个 modelEmployer 但我取回了这个错误
AssertionError at /api/employer/update_profile/employerA@gmail.com/ The `.update()` method does not support writable nested fields by default. Write an explicit `.update()` method for serializer `Employer.api.serializers.Serializer_ListEmployer`, or set `read_only=True` on nested serializer fields. Request Method:
我有两个问题
1-为什么保存失败?
2-如何从上述序列化程序中获取经过验证的数据?
解决方案
The save is failing because django-rest-framework
doesn't deal with nested serializers by default.
from the django-rest-framework docs:
By default nested serializers are read-only. If you want to support write-operations to a nested serializer field you'll need to create create() and/or update() methods in order to explicitly specify how the child relationships should be saved.
You have to override the update
method in the serializer to allow that behavior:
class Serializer_UpdateEmployer(ModelSerializer):
user = Serializer_UpdateUser()
class Meta:
model = modelEmployer
fields = [
'user',
'employer_zip',
]
def update(self, instance, validated_data):
user_data = validated_data.pop('user', {})
user_serializer = Serializer_UpdateUser(instance.user, data=user_data)
user_serializer.save()
return instance
Another solution is to use drf-writable-nested. It automatically makes your nested serializers updatable.
from drf_writable_nested import WritableNestedModelSerializer
class Serializer_UpdateEmployer(WritableNestedModelSerializer):
user = Serializer_UpdateUser()
class Meta:
model = modelEmployer
fields = [
'user',
'employer_zip',
]
推荐阅读
- docker - 清除缓存时的 Simplesaml Auth 错误
- c# - .Net 5.0 中对 WPF 的响应式扩展支持
- shopify - 如何在 Java 文件 Shopify 中使用 Liquid 变量
- html - html 中的图片标签在 Mozilla firefox 上运行良好,但卡在 Google chrome 上
- docker - 连接到在 Gitlab docker executor 中启动的 docker 容器
- javascript - 样式化由 element.append() 方法创建的表格不起作用
- html - 为什么平板电脑屏幕尺寸的卡片重叠?
- javascript - 按键值数组中的值过滤 JavaScript 对象
- cartopy - 安装 cartopy 时出现“ACCEPT_USE_OF_DEPRECATED_PROJ_API_H”错误
- reactjs - 在 React JS 中,我们如何决定是选择 contextAPI 还是 Redux?