Проблема с сохранением пустого поля Base64ImageField в Django Restframework

Я использую пользовательский класс для хранения изображений base64, которые поступают через API запросы.

Класс выглядит следующим образом:

class Base64ImageField(serializers.ImageField):

    def to_internal_value(self, data):

        if isinstance(data, six.string_types):
            if 'data:' in data and ';base64,' in data:
                header, data = data.split(';base64,')

            try:
                decoded_file = base64.b64decode(data)
            except TypeError:
                self.fail('invalid_image')

            file_name = str(uuid.uuid4())[:16] 
            file_extension = self.get_file_extension(file_name, decoded_file)
            complete_file_name = "%s.%s" % (file_name, file_extension, )
            data = ContentFile(decoded_file, name=complete_file_name)

            return super(Base64ImageField, self).to_internal_value(data)

    def get_file_extension(self, file_name, decoded_file):
        import imghdr

        extension = imghdr.what(file_name, decoded_file)
        extension = "jpg" if extension == "jpeg" else extension

        return extension

    def to_representation(self, instance):
        if instance.name:
            return(settings.BASE_URL+reverse('download', args=[instance.name]))
        else:
            return None
    

В моем файле serializer.py я использую его следующим образом:

    logo = Base64ImageField(max_length=None, use_url=True, required=False, allow_null=True, allow_empty_file=True)

Предположим, что логотип уже был сохранен, и теперь я удаляю его, я хочу отправить пустую строку. К сожалению, это всегда заканчивается сообщением об ошибке:

The submitted file is empty.

Я благодарен за любую подсказку.

Я думаю, что вам не нужно создавать Base64ImageField. Вы просто следуете принципу DRY. Пакет django-extra-fields сделает это за вас.

pip install django-extra-fields

В models.py вы просто определяете его как обычный ImageField.

logo = ImageField(max_length=None, use_url=True, required=False, allow_null=True, allow_empty_file=True)

А в сериализаторе можно определить установку Base64ImageField.

from drf_extra_fields.fields import Base64ImageField

class YourModelSerializer(serializers.ModelSerializer):
    logo = Base64ImageField(required = False)

    class Meta:
        fields = '__all__'
        model = YourModel
        
    def create(self, validated_data):
        logo = validated_data.pop('logo')
        created_item = YourModel.objects.create(**validated_data)
        created_item.logo = logo
        created_item.save()
        return True
Вернуться на верх