2

I want to update a model using djangorestframework. I don't need to update all fields, so I use PATCH. However, in my form I also have an image field (called 'logo'), which is required for my model. When I try to 'patch' the object and I don't choose a new image for that field, drf throws an error ('logo': 'This field is required').

I know that when using django forms, file fields get a special treatment, meaning that if they already have a value, submitting the form with an empty filefield will just keep the old value. Is there any way to do that using djangorestframework serializers?

Some code for better understanding:

# 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>  

The best I could come up with for now was to delete the logo entry from my request.DATA before calling the serializer. I am curious if anyone knows a better solution. Thanks.

AdelaN
  • 3,366
  • 2
  • 25
  • 45

1 Answers1

3

Try Link hope fully you will get solution. Or See this cade, hope fully this will work for you.

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