This article explains how to generate PDF documents in Django using different techniques: via Django Shell, generate the document using a GET parameter and pull an image from the internet and use it to build a new (PDF) document. For newcomers, Django 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.
Thanks for reading! - Content provided by App Generator.
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
This tutorial assumes the audience have 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 useful a dedicated Django tutorial that covers the Django basics: Django for Beginners.
Install dependencies using a Virtual Environment
$ 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 ./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:
>>> import os,sys >>> os.startfile('1.pdf', 'open')
startfile helper should open the
$ # Current Dir: ROOT of the Django project $ python manage.py startapp pdf_app
Code a simple PDF generator
# 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.
Using the same
reportlab library we can generate PDF documents with embedded images without much effort - Let's see the code:
# 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
Sample output served by
Once we save the code, Django settings must be updated in order to activate the new app:
# 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
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
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 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 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 a 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.
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.
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.
Thank you! 🚀🚀 Feel free to AMA in the comments section.