如何使用djangorestframework更新ImageField / FileField?

时间:2014-08-28 09:58:54

标签: django django-rest-framework filefield

我想使用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>  

我现在能想到的最好的方法是在调用序列化程序之前从logo删除request.DATA条目。如果有人知道更好的解决方案,我很好奇。感谢。

1 个答案:

答案 0 :(得分:3)

完全尝试Link希望你会得到解决方案。 或者看到这个cade,希望这对你有用。

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