Generate a PDF from HTML in your Django project with xhtml2pdf
While working on a personal Django project I wanted to add a feature where users can download some information as a PDF file. I did it with a library called xhtml2pdf.
In this article, I will discuss with you how to generate PDFs from a Django website using xhtml2pdf. Let’s get started.
Table of Contents:· Project Setup
· Installing Necessary Libraries
· Creating the User model
· Populating the Database With Dummy Data
· Creating Views
· Creating Templates
∘ base.html
∘ main.html
∘ generate_pdf.html
· Creating URLs
· Conclusion
Project Setup
First of all, let’s create a Django project called pdf_proj
.
$ django-admin startproject pdf_proj
It will be a simple project just to demonstrate the process of creating PDFs from HTML so that you can use it as a future reference.
Inside the project, we will create an app named users
.
$ python manage.py startapp users
The users
app is to create users for our project. Where we will populate our database with some dummy user data. Then we will create PDF files from that data.
We will also show images in our PDF files. So we need to handle static and media files in our project. Let’s create two folders called static
and media
in our project root directory. The static images will be stored in the static
folder and images uploaded by users will be stored in the media
folder.
Here is the project structure so far:
├── manage.py
├── media
├── pdf_proj
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-39.pyc
│ │ └── settings.cpython-39.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── static
└── users
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
Now we will install the users
app in the settings.py
file. And also we will add STATIC_ROOT
and MEDIA_ROOT
.
Installing the users app
STATIC_URL and MEDIA_URL
Then we will open the urls.py
file and setup STATIC_URL
and MEDIA_URL
with the urlpatterns
.
And after that, we will create a superuser so that we can access the admin dashboard.
$ python manage.py createsuperuser
The initial project setup is done. Now we can open the development server and check if everything is working ok.
$ python manage.py runserver
Now let’s move on to the users
app.
Installing Necessary Libraries
We need two external libraries for our project. Pillow to handle images and xhtml2pdf to create PDF files. We can install both using pip.
$ pip install pillow
$ pip install xhtml2pdf
You can check out the installation guide on their official documentation:
Creating the User model
We will now create a model inside the users
app. Let’s put the following code in models.py
of the users
app.
Now we need to make migrations and apply the migration.
$ python manage.py makemigrations
$ python manage.py migrate
A table named User
is now created in the database and has three fields: name, logo, and description.
Populating the Database With Dummy Data
Now let’s log in to the admin panel and add some dummy data to the User model. I’ve added five fake users manually to the database so that we can work with them.
Dummy users to work with
Each of the user has a name, a logo, and a description. We will create PDF files with these data.
Each user has three fields
Creating Views
We need two views for the project. A UserListView
where we will list the name of the users. With every name, we will create a button. By clicking this button we will create a PDF with the information of a user. To create PDF files we will need the second view users_render_pdf_view
.
In users_render_pdf_view
I copied most of the code from the documentation of xhtml2pdf. We need to make some minor changes to generate dynamic data from our User
model. Here you can see the code on the documentation to compare where I’ve made the changes:
And UserListView
is just a class-based view to list out all the users. Now we need to create our templates associated with each view.
Creating Templates
We need three HTML files:
base.html
(We will use template inheritance. The other two HTML files will inherit from base.html)main.html
(This will act as the home page. Here we will show the names of the users and for each user, we will create a button to generate PDFs)generate_pdf.html
(Contents of this page will be generated as PDF files. Here we will dynamically generate information of the users)
Inside the users
app let’s create a folder named templates
. Then inside the template
folder let’s create one more folder named users
. Here we will put our HTML files.
└── users
├── templates
│ └── users
│ ├── base.html
│ ├── generate_pdf.html
│ └── main.html
base.html
main.html
generate_pdf.html
Now we need to create separate URLs for each view.
Creating URLs
For this, we need to modify our project urls.py
file. We can also create a separate urls.py
file for our app and then include it in the project. However, to keep things simple I’ve created the URLs directly in the project urls.py
.
And that’s pretty much it. Let’s see how the application looks like.
User list
This is the home page of our application. All the users are displayed here. Alongside the user’s name we have a button that says “Download pdf”. If we click the button we will be redirected to a new window where a PDF file with the information of a user will be created. Suppose we clicked the button beside User 3. The information of User 3 will appear in PDF format by clicking it.
Generated PDF
Of course, by clicking on some other user the information will change accordingly. We can also download the PDF and store it locally.
Conclusion
In this article, I showed you how to create PDFs from a Django website by creating a small project. I hope you find it helpful. Thanks for your time.
The source code is available on GitHub. I have also provided all the images used in this project. Here is the GitHub repository of the project. You can use the code from there.