Django генерирует файл и сохраняет его в модели

Мое приложение Django генерирует файл. Оно берет img1.png и watermark.png, вставляет их вместе и снова сохраняет в папке.

Все работает так, как ожидалось.

Это функция:

def generate():
    img1 = Image.open(f'{current_path}/media/pdf/img1.png')
    img2 = Image.open(f'{current_path}/media/watermark.png')
    img1.paste(img2, (150, 250), img2)
    img1.save(f'{current_path}/media/pdf/generatedfile.png')

При локальной работе на моем компьютере все хорошо с указанием пути. Однако в продакшене это больше не работает. Мне нужно сохранить generatedfile.png непосредственно на AWS S3.

Для этого я создал простую модель:

class pngUploadModel(models.Model):
     auto_increment_id = models.AutoField(primary_key=True, default=True)
     image = models.ImageField(null=True, blank=True, upload_to="png/")

Я могу загружать изображения в эту модель с помощью интерфейса администратора. Все работает, как и ожидалось.

Теперь перейдем к моей проблеме. Мне нужно сгенерировать изображение и сохранить его "напрямую" в модель. Не сохраняя его сначала в путь (потому что это не будет работать в производстве).

Подход:

   def generate():
        img1 = Image.open(f'{current_path}/media/pdf/img1.png')
        img2 = Image.open(f'{current_path}/media/watermark.png')
        img1.paste(img2, (150, 250), img2)
        img1.save(f'{current_path}/media/pdf/generatedfile.png')

        try:
             filename = pngUploadModel.objects.create()
             filename.image = img2
             print('worked!')
        except Exception as e:
             print(f'this is the error message: {e}')

Вывод: Он создает объект в моей модели, который я могу видеть на моей панели администратора, но модель пуста, там нет изображения.

Как я могу сохранить сгенерированное изображение в моей модели, не сохраняя его сначала в локальной директории. Я думал использовать что-то вроде tempfile, но не знаю, правильный ли это способ.

Если я правильно понял, вы хотите получить сгенерированный файл из пути к файлу (f'{current_path}/media/pdf/generatedfile.png') и сохранить его в вашем pngUploadModel.

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

def generate():
    img1 = Image.open(f'{current_path}/media/pdf/img1.png')
    img2 = Image.open(f'{current_path}/media/watermark.png')
    img1.paste(img2, (150, 250), img2)
    img1.save(f'{current_path}/media/pdf/generatedfile.png') 
    # the prefix string of the generated file -> f'{current_path}/media/pdf/generatedfile.png'

    try:
         genFile = pngUploadModel()
         # Using the path/prefix of the generated file to be set to the image field
         genFile.image = f'{current_path}/media/pdf/generatedfile.png'
         genFile.save()
         print('worked!')
    except Exception as e:
         print(f'this is the error message: {e}')

Я использовал этот ответ в качестве руководства, и он отлично сработал.

Другой способ - сохранить сгенерированный файл в поле image, передав несколько аргументов в save() на поле image/file. Пример:

from django.core.files.base import ContentFile  # ensure you import

def generate():
    prefix = f'{current_path}/media/pdf/generatedfile.png'

    img1 = Image.open(f'{current_path}/media/pdf/img1.png')
    img2 = Image.open(f'{current_path}/media/watermark.png')
    img1.paste(img2, (150, 250), img2)
    img1.save(prefix) 
    # the prefix string of the generated file -> f'{current_path}/media/pdf/generatedfile.png'

    # with open('/path/to/already/existing/file', 'rb') as f:
    with open(prefix, 'rb') as f:
        data = f.read()

        genFile = pngUploadModel()

        genFile.image.save('generatedfile.png', ContentFile(data))
        genFile.save()

Идеально, это должно сработать. Вы также можете просмотреть другие ответы на этот вопрос, так как они могут быть полезны или могут быть использованы в будущем.

Вернуться на верх