I am trying to create a new instance of a model that has an image field in it. I take a PDF from a form and convert it to a png file format and am now trying to save the png image to a model data base but get the error 'PngImageFile' object has no attribute '_committed'. I know you cant save an image directly to a data base but i'm wondering how can you save the image to the media folder and save the image url path to the image in the data base? Help greatly appreciated.
This is my form to take in the PDF (forms.py)
class DrawingPDFForm(forms.Form):
drawing_name = forms.CharField(max_length=50)
file = forms.FileField()
This is my view to convert PDF to PNG and then create new instance of model to save to database(views.py)
def upload_drawings(request):
if request.method == "POST":
form = DrawingPDFForm(request.POST, request.FILES)
drawing_name = request.POST['drawing_name']
file = request.FILES['file']
pdf_byt = file.read()
pdf_content = BytesIO(pdf_byt)
pdf_content.seek(0)
pdf_converted = convert_from_bytes(pdf_content.read(), poppler_path=r"C:\Python\Python\Programs\plant_locator\poppler\poppler-23.07.0\Library\bin")
buffer = BytesIO()
pdf_converted[0].save(buffer, 'png')
png_byt = buffer.getvalue()
my_string = base64.b64encode(png_byt)
pdf_png_byt_decode = base64.b64decode(my_string)
png = Image.open(BytesIO(pdf_png_byt_decode))
drawing = Drawing.objects.create(drawing_name=drawing_name, drawing=png)#error occurs here as #expected
drawing.save()
return HttpResponseRedirect('/upload_drawings')
else:
form = DrawingPDFForm()
return render(request, 'upload_drawings.html', {'form':form})
This is my model I am trying to create a new instance of (models.py)
from django.db import models
class Drawing(models.Model):
drawing_name = models.CharField('Drawing Name', max_length=50)
drawing = models.ImageField(null=True, blank=True, upload_to="images/")
def __str__(self):
return self.drawing_name
this is what comes to my mind
in your "url.py" file add the following line at the end of your "urlpatterns":
from djano.conf import settings
from django .conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
and now you should modify your view to save image to the media folder and store the image path in the model:
from django.core.files.uploadedfile import SimpleUploadedFile
import os
def upload_drawings(request):
if request.method == "POST":
form = DrawingPDFForm(request.POST, request.FILES)
drawing_name = request.POST['drawing_name']
file = request.FILES['file']
# Convert PDF to PNG
pdf_byt = file.read()
pdf_content = BytesIO(pdf_byt)
pdf_content.seek(0)
pdf_converted = convert_from_bytes(pdf_content.read(), poppler_path=r"C:\Python\Python\Programs\plant_locator\poppler\poppler-23.07.0\Library\bin")
buffer = BytesIO()
pdf_converted[0].save(buffer, 'png')
# Save PNG to the media folder
png_byt = buffer.getvalue()
drawing_path = os.path.join('images', f'{drawing_name}.png')
drawing_file = SimpleUploadedFile(drawing_path, png_byt, content_type='image/png')
# Create and save the Drawing instance
drawing = Drawing.objects.create(drawing_name=drawing_name, drawing=drawing_file)
return HttpResponseRedirect('/upload_drawings')
else:
form = DrawingPDFForm()
return render(request, 'upload_drawings.html', {'form': form})
and make sure you have configured the media settings in your django project:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
I hope this helps you.