Create PDF documents in Django - Tutorial for Beginners
Tags: beginners, python, django
Published: 2021-06-22 10:36:23

---
title: Create PDF documents in Django - Tutorial for Beginners
published: true
description: Learn how to generate dynamic PDF documents in Django - tutorial for beginners
tags: beginners, python, django
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cuub5y6jxgx4jh7fbu3q.jpg
---
Hello Coders,

This article explains how to **generate PDF documents** in **Django** using different techniques: via Django Shell, generate the document using a GET parameter pull an image from the internet, and use it to build a new (PDF) document. 

> 👉 [Django Apps](https://appseed.us/apps/django/) a curated index with projects

For newcomers, **[Django](https://www.djangoproject.com/)** is an open-source web framework designed by experienced developers that we can use to code from simple one-page projects to complex APIs and eCommerce platforms. 

> **Topics covered** in this tutorial

- ✅ Built a new Django App
- ✅ Configure Django to activate the new app
- ✅Add/explain code for each case
    - Generate the PDF using Django CLI
    - Generate a (simple) dynamic PDF in a new page
    - Generate a dynamic PDF using an image
- ✅ Mention a few open-source [Django Templates](https://appseed.us/admin-dashboards/django/)

---

## Create PDF using Django CLI

This tutorial assumes the audience has already a Django project and we will add a new `app` that implements the PDF generation process. Complete beginners without a working project might find a dedicated Django tutorial that covers the Django basics: [Django for Beginners](https://docs.appseed.us/content/tutorials/django-for-beginners). 

---

> Install dependencies using a Virtual Environment

```bash
$ virtualenv env           # create a VENV
$ source env/bin/activate  # activate VENV
$
$ pip install reportlab
```

`reportlab` is the library that brings all the PDF magic to our app. Let's use it and create a simple PDF document right in the Django shell:

```python
$ python ./manage.py shell                   # start Django CLI
>>>
>>> import reportlab                         # import the library
>>> from reportlab.pdfgen import canvas      # import modules 
>>> p = canvas.Canvas('1.pdf')               # Init a PDF object
>>> p.drawString(200, 200, "Hello world.")   # Draw a simple String  
>>> p.showPage()                             # Create the PDF
>>> p.save()                                 # Clean UP the library usage
```

Once all instructions are executed, we should see a new PDF file created in the root of our Django project. Let's open the file, without leaving the Django shell:

```python
>>> import os,sys
>>> os.startfile('1.pdf', 'open')
```

The `startfile` helper should open the `PDF` file using the default handler registered in the operating system.

---

![Generate PDF in Django - Simple Hello World.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1kubp9ludvw7nm830fy9.jpg)

---   

## Create the new Django app

```bash
$ # Current Dir: ROOT of the Django project
$ python manage.py startapp pdf_app
```

> **Code a simple PDF generator**

```python
# File contents: `app_pdf/views.py` (partial content)
...
from reportlab.pdfgen    import canvas
from reportlab.lib.utils import ImageReader
from datetime            import datetime
...

def pdf_dw(request):                                  

    # Create the HttpResponse object 
    response = HttpResponse(content_type='application/pdf') 

    # This line force a download
    response['Content-Disposition'] = 'attachment; filename="1.pdf"' 
 
    # READ Optional GET param
    get_param = request.GET.get('name', 'World')
    
    # Generate unique timestamp
    ts = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')

    p = canvas.Canvas(response)
    
    # Write content on the PDF 
    p.drawString(100, 500, "Hello " + get_param + " (Dynamic PDF) - " + ts ) 
 
    # Close the PDF object. 
    p.showPage() 
    p.save() 

    # Show the result to the user    
    return response
```

This simple PDF generator will set a few properties to the `HttpResponse` object returned to the user, read an optional GET parameter and generate a timestamp saved in the PDF. Once the new PDF is saved in memory, we can return the contents to the user. 

> Sample Usage: `http://localhost:8000/pdf_dw/?name=Bill Gates`

![Generate PDF in Django - Dynamic content with GET parameter.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mjb5bi21b0kusu9l0q5g.jpg)

--- 

## Generate PDF with an Image

Using the same `reportlab` library we can generate PDF documents with embedded images without much effort - Let's see the code:

```python
# File contents: `app_pdf/views.py` (partial content)
...
from reportlab.pdfgen    import canvas
from reportlab.lib.utils import ImageReader
from datetime            import datetime
...

def pdf_img(request):                                  

    # Create the HttpResponse object with the appropriate PDF headers. 
    response = HttpResponse(content_type='application/pdf') 
 
    # Create the PDF object, using the response object as its "file." 
    p = canvas.Canvas(response)     

    my_image = ImageReader('https://www.google.com/images/srpr/logo11w.png')
    
    p.drawImage(my_image, 10, 500, mask='auto')

    # Close the PDF object. 
    p.showPage() 
    p.save() 

    # Show the result to the user    
    return response
``` 

`my_image` object is the Google logo, downloaded from a public address and used in our PDF via `drawImage` directive. 

> Sample output served by `http://localhost:8000/pdf_img/`

![Generate PDF in Django - Dynamic content with Image Object.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h630fv3183ext26f8kk7.jpg)

--- 

Once we save the code, Django settings must be updated in order to activate the new app: 

```python
# Update Django Settings.py
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app_pdf',
]
...
``` 

> Update Project Routing

```python
urlpatterns = [
    path('admin/', admin.site.urls),
    path(""    , include("app_pdf.urls")),   # <-- NEW
]
```

---

> **Thanks for Reading!** For questions related Django and PDF generation process, feel free to AMA in the comments section. 

--- 

## ✅ More [Django Templates](https://appseed.us/admin-dashboards/django/)

The open-source samples presented in this section might help beginners (and not only) to code faster a new project in Django by  reusing codebase and provided features. 

### 👉 [Black Dashboard Django](https://appseed.us/product/black-dashboard/django/)

Black Dashboard Django features over 16 individual components, giving you the freedom of choosing and combining. This means that there are thousands of possible combinations. All components can take variations in color, that you can easily modify using SASS files. You will save a lot of time going from prototyping to full-functional code because all elements are implemented. We thought about everything, so this dashboard comes with 2 versions, Dark Mode and Light Mode.

- 👉 [Django Black Dashboard](https://appseed.us/product/black-dashboard/django/) - `Product page`
- 👉 [Django Black Dashboard](https://django-black-dashboard.appseed-srv1.com/) - `LIVE Demo`

**Django Codebase** is crafted using a simple, modular structure that follows the best practices and provides authentication, database configuration, and deployment scripts for Docker and Gunicorn/Nginx stack. Any developer with basic Django/Python knowledge, by following the product documentation should be able to compile and use the app by typing only a few lines in the terminal.

![Django Admin Black - Template project for Django provided by AppSeed.](https://user-images.githubusercontent.com/51070104/196730732-dda1794b-93ce-48cb-bc5c-182411495512.png)

---

### 👉 [Django Argon Dashboard](https://appseed.us/product/argon-dashboard/django/)

Argon Dashboard is built with over 100 individual components, giving you the freedom of choosing and combining. All components can take variations in color, that you can easily modify using SASS files. You will save a lot of time going from prototyping to full-functional code, because all elements are implemented. This Dashboard is coming with pre-built examples, so the development process is seamless, switching from our pages to the real website is very easy to be done.

- 👉 [Django Argon Dashboard](https://appseed.us/product/argon-dashboard/django/) - `Product page`
- 👉 [Django Argon Dashboard](https://django-argon-dash2.onrender.com) - `LIVE Demo`

![Argon Dashboard 2 - Free Starter.](https://user-images.githubusercontent.com/51070104/215804889-94eba681-8262-41a3-8e57-7d5b12dcc209.png)

---

### 👉 [Django Material Dashboard](https://appseed.us/product/material-dashboard/django/)

Material Dashboard makes use of light, surface and movement. The general layout resembles sheets of paper following multiple different layers, so that the depth and order is obvious. The navigation stays mainly on the left sidebar and the content is on the right inside the main panel.

- 👉 [Django Material Dashboard](https://appseed.us/product/material-dashboard/django/) - `Product page`
- 👉 [Django Material Dashboard](https://django-material-dash2.onrender.com) - `LIVE Demo`

![Material Dashboard - Full-Stack Starter generated by AppSeed.](https://user-images.githubusercontent.com/51070104/169301658-6cf27993-c451-4cd4-9ffa-2968b8981167.png)

--- 

## ✅ Resources

- 👉 Access [AppSeed](https://appseed.us/) and start your next project
- 👉 [Django App Generator](https://app-generator.dev/django/) - A 2nd generation App Builder