Как сохранить файл содержимого в поле 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...)