Проблема с сохранением пустого поля 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