我想使用djangorestframework更新一个模型。我不需要更新所有字段,所以我使用PATCH。然而,在我的表单中,我也有一个图像字段(称为"徽标"),这是我的模型所必需的。当我尝试"修补"对象,但没有为该字段选择新图像时,drf会抛出一个错误("登录":"此字段是必需的")。
我知道,当使用django表单时,文件字段会得到特殊处理,这意味着如果它们已经有了值,那么提交带有空文件字段的表单将只保留旧值。使用djangorestframework序列化程序有什么方法可以做到这一点吗?
一些更好理解的代码:
# models.py
class Brand(models.Model):
name = models.CharField(_('name'), max_length=250)
logo = models.ImageField(upload_to='brands/')
# serializers.py
class BrandSerializer(serializers.ModelSerializer):
class Meta:
model = Brand
fields = (
'id',
'name',
'logo',
)
# detail.html
<form method="post" enctype="multipart/form-data">
{%csrf_token%}
<input name="name" type="text" maxlength="30" value="{{ brand.name }}"/>
<input name="logo" type="file" accept="image/*"/>
<input name="_method" type="hidden" value="PATCH">
<input type="submit" value="Update"/>
</form>
目前我能想到的最好办法是在调用序列化程序之前从request.DATA
中删除logo
条目。我很好奇是否有人知道更好的解决方案。谢谢
尝试链接,希望您能完全得到解决方案。或者看看这个学员,希望这对你有用。
class ImageSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Brand
fields = ('name', 'logo')
def saveImage(self, imgFileUri):
#parse dataUri and save locally, return local path
return 'somewhereOverTheBlah'
def restore_fields(self, data, files):
reverted_data = {}
if data is not None and not isinstance(data, dict):
self._errors['non_field_errors'] = ['Invalid data']
return None
for field_name, field in self.fields.items():
"""
So it is iterating over the fields to serialize, when we find the file field
do something different (in this case look for the fileUri field, handle it and replace
it inside of the reverted_data dictionary with the intended file field
"""
if(field_name == 'file'):
field_name = 'dataUri'
field = fields.CharField()
try:
# restore using the built in mechanism
field.field_from_native(data, files, field_name, reverted_data)
# take the dataUri, save it to disk and return the Path
value = reverted_data[field_name]
path = self.saveImage(value)
# set the file <Path> property on the model, remove the old dataUri
reverted_data['file'] = path
del reverted_data[field_name]
except ValidationError as err:
self._errors[field_name] = list(err.messages)
else:
field.initialize(parent=self, field_name=field_name)
try:
field.field_from_native(data, files, field_name, reverted_data)
except ValidationError as err:
self._errors[field_name] = list(err.messages)
return reverted_data