В моей форме у меня есть ImageField, а также скрытый CharField для принятия изображения в качестве base64. Когда пользователь выбирает изображение в форме внешнего интерфейса, мой JS-скрипт на внешнем интерфейсе автоматически изменяет размер изображения как холста, а затем устанавливает сгенерированный dataUrl в качестве содержимого для CharField. Мне бы хотелось, чтобы при отправке формы я мог преобразовать текст base64 в изображение и переопределить сохранение исходного изображения в ImageField, чтобы вместо него сохранялось декодированное изображение base64 (имя файла и все).
Я следовал нескольким учебным пособиям онлайн, которые помогли мне сформулировать код ниже. Я переписал функцию clean()
в моем forms.py
, чтобы текст base64 был декодирован в изображение PIL. Теперь я хотел бы установить его вместо реального содержимого ImageField, чтобы оно сохранялось и обрабатывалось так, как будто декодированное изображение base64 было файлом, отправленным в POST.
В других ответах предлагается сохранить декодированное изображение base64 вручную с помощью команды with open()
, но такой подход открывает другие головные боли. Тем более, что Django уже обрабатывает переименование изображения, если изображение отправлено с именем, которое уже существует. Я бы предпочел не переделывать колесо для этого. Замена файла ImageField на созданный непосредственно перед сохранением с помощью встроенных методов Django кажется наилучшим подходом.
Есть ли способ, которым мой желаемый подход возможен? Я не нашел ни одного ответа, который пытался бы справиться с этим сценарием без необходимости вручную сохранять файл и впоследствии обновлять модель.
from PIL import Image
from io import BytesIO
import os
import sys
import re
import base64
def clean(self):
cleaned_data = super().clean()
dataUrlPattern = re.compile('data:image/(png|jpeg);base64,(.*)$')
ImageData = cleaned_data.get("image_base64_text")
ImageData = dataUrlPattern.match(ImageData).group(2)
ogImg = cleaned_data.get("image")
# If none or len 0, means illegal image data
if (ImageData == None or len(ImageData) == 0):
# PRINT ERROR MESSAGE HERE
print('corrupt or illegal image data')
# Decode the 64 bit string into 32 bit
ImageData = base64.b64decode(ImageData)
ImageData = Image.open(BytesIO(ImageData))