PDF object list view with the first page as cover of the object

Hello,

I need your support on the below idea:
I need to create a simple app to upload pdf files from the admin panel, then show those pdf files by a listView in a html to the visitors in a way that the first page of those pdf objects be shown as the object itself.
I am using django==3.2
Do I need to use JS or … to get this done.

your hints and guidance is highly appreciated.

1 Like

My initial reaction to this is to create a second field in your model to hold the image of page 1. Your model would then have two fields, a FileField for the PDF and an ImageField for the page 1 image.

When a file is upload, you would then run whatever you wanted to run to generate an image from the first page of the file and save the reference to in your model. Your ListView could then include the URL created for that image in your page.

2 Likes

Thank you for your help.

Hello,

Thanks again for your guidance. I have the below code that I used in Django 3.2 which works fine except in 1 point:

models.py
from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator 

# Create your models here.

from django.core.validators import FileExtensionValidator
from django.db.models.signals import post_save, pre_save
from pdf2image import convert_from_path
from django.conf import settings
import os


COVER_PAGE_DIRECTORY = 'library_app/coverdirectory/'
PDF_DIRECTORY = 'library_app/pdfdirectory/'
COVER_PAGE_FORMAT = 'jpg'

# this function is used to rename the pdf to the name specified by filename field
def set_pdf_file_name(instance, filename):
    return os.path.join(PDF_DIRECTORY, '{}.pdf'.format(instance.filename))

# not used in this example
def set_cover_file_name(instance, filename):
    return os.path.join(COVER_PAGE_DIRECTORY, '{}.{}'.format(instance.filename, COVER_PAGE_FORMAT))

class Pdffile(models.Model):
    # validator checks file is pdf when form submitted
    pdf = models.FileField(
        upload_to=set_pdf_file_name, 
        validators=[FileExtensionValidator(allowed_extensions=['pdf'])]
        )
    filename = models.CharField(max_length=50)
    pagenumforcover = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1), MaxValueValidator(1000)])
    coverpage = models.FileField(blank=True, upload_to=set_cover_file_name)

def convert_pdf_to_image(sender, instance, created, **kwargs):
    if created:
        # check if COVER_PAGE_DIRECTORY exists, create it if it doesn't
        # have to do this because of setting coverpage attribute of instance programmatically
        cover_page_dir = os.path.join(settings.MEDIA_ROOT, COVER_PAGE_DIRECTORY)

        if not os.path.exists(cover_page_dir):
            os.mkdir(cover_page_dir)

        # convert page cover (in this case) to jpg and save
        cover_page_image = convert_from_path(
            pdf_path=instance.pdf.path,
            dpi=50, 
            first_page=instance.pagenumforcover, 
            last_page=instance.pagenumforcover, 
            fmt=COVER_PAGE_FORMAT, 
            output_folder=cover_page_dir,
            )[0]

        # get name of pdf_file 
        pdf_filename, extension = os.path.splitext(os.path.basename(instance.pdf.name))
        new_cover_page_path = '{}.{}'.format(os.path.join(cover_page_dir, pdf_filename), COVER_PAGE_FORMAT)
        # rename the file that was saved to be the same as the pdf file
        os.rename(cover_page_image.filename, new_cover_page_path)
        # get the relative path to the cover page to store in model
        new_cover_page_path_relative = '{}.{}'.format(os.path.join(COVER_PAGE_DIRECTORY, pdf_filename), COVER_PAGE_FORMAT)
        instance.coverpage = new_cover_page_path_relative

        # call save on the model instance to update database record
        instance.save()

post_save.connect(convert_pdf_to_image, sender=Pdffile)

When I create an object, then a jpg is created. The problem is when I open the object in django admin panel and change the Pagenumforcover to something else it won’t update, or if I delete the current Pagenumforcover and save then it won’t auto generate a new Pagenumforcover.
This topic is complicated for me. Kindly I would appreciate your help.

First a side note. When posting code here, please enclose the code between lines of three backtick - ` characters. This means you’ll have a line of ```, then your code, then another line of ```. This forces the forum software to keep your code properly formatted, which is critical with Python.

Now a couple of thoughts -

First, and image field in a model does not mean that the field is stored in the database. What is actually stored in the database is a reference to the file, which is stored somewhere else.

Django does not itself alter the contents of files stored. That’s code you would need to provide. If you need to change or regenerate an image, that’s code that you need to write and add to your ModelAdmin class. Review the docs at The Django admin site | Django documentation | Django to see what your options are.