Django: использование base64 для хранения изображений в БД

#python #django #file #base64 #storage

#python #django #файл #base64 #Хранение

Вопрос:

models.py:

 class Empresa(models.Model):
    logo = models.FileField(null=True)
  

forms.py:

 class ConfiEmpresa(ModelForm):
    logo = forms.FileField(required=False)
    class Meta:
        model = Empresa
  

Следующий код ввода html, который отображается в поле формы:

 <input type="file" name="logo" id="id_logo">
  

views.py:

 import base64

def configempresa(request):
    if request.method == "POST":
        form = ConfiEmpresa(request.POST, request.FILES)
        print(form.errors)  # I'm not having any form error here
        if form.is_valid():
            logo = form.cleaned_data.get('logo')
            print(logo)  # It's printing "None"
            logo = base64.encodebytes(logo)
            #...rest of the view
  

Ошибка, которую я получаю:

 TypeError at /Config/empresa/
expected bytes-like object, not NoneType
  

Итак, в заключение я пытаюсь преобразовать файл jpg, который пользователь задает как ‘logo’, в base64, чтобы сохранить его в моей БД и позже декодировать его, чтобы получить изображение там, где оно мне нужно.

Конечно, я делаю что-то не так, я думаю, это на мой взгляд. Как я могу обработать значение поля формы logo , чтобы преобразовать его в base64?

Я не сохраняю необработанный файл ни в какой папке.

Комментарии:

1. Вы уверены, что ваш файл отправлен? Если вы проверите, request.FILES есть ли там что-нибудь? Кроме того, использовали ли вы <form enctype="multipart/form-data" ...> в качестве типа кодировки формы?

2. Кроме того, учитывая, что ваше поле является required=False , это означает, что вы разрешаете НЕ отправлять файл, поэтому вам нужно будет обработать случай, когда логотип не загружается.

3. Спасибо @Geekfish. Ну, тип enctype был частью проблемы. Это было в «application / x-www-form-urlencoded». Теперь он больше не выводит «None», но ошибка теперь такая: «ожидаемый байтоподобный объект, а не InMemoryUploadedFile»

4. Также мне интересно, правильно ли «logo = form.cleaned_data.get(‘logo’)» и «logo = base64.encodebytes(logo)»?

5. Подсказка содержится в сообщении об ошибке. Вы пытаетесь передать InMemoryUploadedFile объект ( logo ) в base64.encodebytes , который, как следует из названия, ожидает байты. InMemoryUploadedFile является оболочкой вокруг фактического файла. Вам нужно получить фактическое содержимое файла. Что-то вроде base64.encodebytes(logo.file.read()) . Но я не уверен в точном способе. Возможно, вам потребуется поискать, как именно это сделать.

Ответ №1:

Не было бы лучше сохранить логотип в ImageField ?

Если вы хотите сохранить изображение base64, вы всегда можете сохранить его в TextField виде строки, если вы только хотите показать изображение позже.

Комментарии:

1. Это неверный ответ на вопрос, однако предложение использовать TextField хорошее.

2. Да, текстовое поле в модели. Форма подходит для FileField.

Ответ №2:

Решение:

 if form.is_valid():
            logo = form.cleaned_data.get('logo')
            print(logo)
            logo = base64.b64encode(logo.file.read())