Как сохранить изображение base64 из html5 canvas как ImageField в Django? - PullRequest
0 голосов
/ 29 апреля 2019

В моей форме у меня есть 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))

1 Ответ

0 голосов
/ 29 апреля 2019

Определите метод clean_image в форме и верните экземпляр InMemoryUploadedFile из метода clean.Ps Я рекомендую вам использовать руководство по стилю pep8 s для именования переменных и других вещей, связанных со стилем кода.

def clean_image(self):
    dataUrlPattern = re.compile('data:image/(png|jpeg);base64,(.*)$')
    ImageData = self.cleaned_data.get("image_base64_text")
    ImageData = dataUrlPattern.match(ImageData).group(2)

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


    return InMemoryUploadedFile(ImageData,
                            'ImageField', 'filename'),
                            'image/jpeg',
                            sys.getsizeof(output),
                            None)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...