Как сохранить файл содержимого в поле ImageField в Django

Я пытаюсь преобразовать изображение, загруженное пользователем, в PDF, а затем сохранить его в ImageField в mysql database, используя form, но сталкиваюсь с ошибкой при попытке сохранить PDF в базе данных

Мой views.py имеет вид:

from django.core.files.storage import FileSystemStorage
from PIL import Image
import io
from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.core.files.base import ContentFile

def formsubmit(request):                        #submits the form
    docs = request.FILES.getlist('photos')
    print(docs)
    section = request.POST['section']
    for x in docs:
        fs = FileSystemStorage()
        print(type(x.size))
        img = Image.open(io.BytesIO(x.read()))
        imgc = img.convert('RGB')
        pdfdata = io.BytesIO()
        imgc.save(pdfdata,format='PDF')
        thumb_file = ContentFile(pdfdata.getvalue())
        filename = fs.save('photo.pdf', thumb_file)
        linkobj = Link(link = filename.file, person = Section.objects.get(section_name = section), date = str(datetime.date.today()), time = datetime.datetime.now().strftime('%H:%M:%S'))
        linkobj.save()
        count += 1
        size += x.size  
    return redirect('index')

Мой models.py:

    class Link(models.Model):
    id      = models.BigAutoField(primary_key=True)
    person  = models.ForeignKey(Section, on_delete=models.CASCADE)
    link    = models.ImageField(upload_to= 'images', default = None)
    date    = models.CharField(max_length=80, default = None)
    time    = models.CharField(max_length=80,default = None)

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

AttributeError: 'str' object has no attribute 'file'

Другие методы, которые я пробовал:

1) linkobj = Link(link = thumb_file, person = Section.objects.get(section_name = section), date = str(datetime.date.today()), time = datetime.datetime.now().strftime('%H:%M:%S'))

РЕЗУЛЬТАТ ВЫШЕУКАЗАННОГО МЕТОДА: 1) thumb_file не выдает ошибку, а скорее ничего не сохраняет в базе данных

Точки, которые я заметил:

1) Файл правильно сохраняется в папке media, т.е. я вижу, что pdf сохраняется в папке media

Как мне решить эту проблему? Спасибо

Ок, я нашел ответ, если честно, я не могу принять свой собственный ответ, так как он не дает точного ответа на вопрос, который я задал, скорее это другой метод, так что если кто-то знает, пожалуйста, поделитесь, чтобы сообщество могло извлечь пользу:

Мое решение: Вместо использования ContentFile я использовал InMemoryUploadedFile для хранения преобразованного pdf, а затем перенес его в базу данных (в ImageField)

Буду честен, я не совсем уверен в том, почему ContentFile не работает, но при изучении документации я обнаружил, что :

Класс ContentFile наследуется от File, но в отличие от File он оперирует содержимым строки (также поддерживаются байты), а не реального файла.

Любое подробное объяснение приветствуется

Мой новый views.py

from django.core.files.storage import FileSystemStorage
from PIL import Image
import io
from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.core.files.base import ContentFile
import sys

def formsubmit(request):                        #submits the form
    docs = request.FILES.getlist('photos')
    print(docs)
    section = request.POST['section']
    for x in docs:
        fs = FileSystemStorage()
        print(type(x.size))
        img = Image.open(io.BytesIO(x.read()))
        imgc = img.convert('RGB')
        pdfdata = io.BytesIO()
        imgc.save(pdfdata,format='PDF')
        thumb_file = InMemoryUploadedFile(pdfdata, None, 'photo.pdf', 'pdf',sys.getsizeof(pdfdata), None)
        linkobj = Link(link = thumb_file, person = Section.objects.get(section_name = section), date = str(datetime.date.today()), time = datetime.datetime.now().strftime('%H:%M:%S'))
        linkobj.save()
        count += 1
        size += x.size  
    return redirect('index')

Если у вас есть вопрос, вы можете оставить его в комментариях, и я постараюсь ответить на него, Удачи!!!

Вам не нужно (практически никогда) самостоятельно инициализировать хранилище. Это особенно актуально, поскольку хранилище для поля может вообще не быть FileSystemStorage, а, например, поддерживаться S3.

Что-то вроде

import datetime
import io

from PIL import Image
from django.core.files.base import ContentFile


def convert_image_to_pdf_data(image):
    img = Image.open(io.BytesIO(image.read()))
    imgc = img.convert("RGB")
    pdfdata = io.BytesIO()
    imgc.save(pdfdata, format="PDF")
    return pdfdata.getvalue()


def formsubmit(request):  # submits the form
    photos = request.FILES.getlist("photos")  # list of UploadedFiles
    section = request.POST["section"]
    person = Section.objects.get(section_name=section)
    date = str(datetime.date.today())
    time = datetime.datetime.now().time("%H:%M:%S")
    count = 0
    size = 0
    for image in photos:
        pdfdata = convert_image_to_pdf_data(image)
        thumb_file = ContentFile(pdfdata, name="photo.pdf")
        Link.objects.create(
            link=thumb_file,
            person=person,
            date=date,
            time=time,
        )
        count += 1
        size += image.size
    return redirect("index")

здесь должно быть достаточно, т.е. использование ContentFile для конвертированного содержимого PDF; поле должно заниматься сохранением его в хранилище.

(В качестве примера, почему дата и время хранятся отдельно как строки? В вашей базе данных наверняка есть тип datetime...)

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