mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			120 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| ===========================
 | |
| Outputting PDFs with Django
 | |
| ===========================
 | |
| 
 | |
| This document explains how to output PDF files dynamically using Django views.
 | |
| This is made possible by the excellent, open-source ReportLab_ Python PDF
 | |
| library.
 | |
| 
 | |
| The advantage of generating PDF files dynamically is that you can create
 | |
| customized PDFs for different purposes -- say, for different users or different
 | |
| pieces of content.
 | |
| 
 | |
| For example, Django was used at kusports.com_ to generate customized,
 | |
| printer-friendly NCAA tournament brackets, as PDF files, for people
 | |
| participating in a March Madness contest.
 | |
| 
 | |
| .. _ReportLab: https://www.reportlab.com/opensource/
 | |
| .. _kusports.com: http://www.kusports.com/
 | |
| 
 | |
| Install ReportLab
 | |
| =================
 | |
| 
 | |
| The ReportLab library is `available on PyPI`_. A `user guide`_ (not
 | |
| coincidentally, a PDF file) is also available for download.
 | |
| You can install ReportLab with ``pip``:
 | |
| 
 | |
| .. console::
 | |
| 
 | |
|     $ pip install reportlab
 | |
| 
 | |
| Test your installation by importing it in the Python interactive interpreter::
 | |
| 
 | |
|     >>> import reportlab
 | |
| 
 | |
| If that command doesn't raise any errors, the installation worked.
 | |
| 
 | |
| .. _available on PyPI: https://pypi.org/project/reportlab/
 | |
| .. _user guide: https://www.reportlab.com/docs/reportlab-userguide.pdf
 | |
| 
 | |
| Write your view
 | |
| ===============
 | |
| 
 | |
| The key to generating PDFs dynamically with Django is that the ReportLab API
 | |
| acts on file-like objects, and Django's :class:`~django.http.FileResponse`
 | |
| objects accept file-like objects.
 | |
| 
 | |
| Here's a "Hello World" example::
 | |
| 
 | |
|     import io
 | |
|     from django.http import FileResponse
 | |
|     from reportlab.pdfgen import canvas
 | |
| 
 | |
|     def some_view(request):
 | |
|         # Create a file-like buffer to receive PDF data.
 | |
|         buffer = io.BytesIO()
 | |
| 
 | |
|         # Create the PDF object, using the buffer as its "file."
 | |
|         p = canvas.Canvas(buffer)
 | |
| 
 | |
|         # Draw things on the PDF. Here's where the PDF generation happens.
 | |
|         # See the ReportLab documentation for the full list of functionality.
 | |
|         p.drawString(100, 100, "Hello world.")
 | |
| 
 | |
|         # Close the PDF object cleanly, and we're done.
 | |
|         p.showPage()
 | |
|         p.save()
 | |
| 
 | |
|         # FileResponse sets the Content-Disposition header so that browsers
 | |
|         # present the option to save the file.
 | |
|         return FileResponse(buffer, as_attachment=True, filename='hello.pdf')
 | |
| 
 | |
| The code and comments should be self-explanatory, but a few things deserve a
 | |
| mention:
 | |
| 
 | |
| * The response will automatically set the MIME type :mimetype:`application/pdf`
 | |
|   based on the filename extension. This tells browsers that the document is a
 | |
|   PDF file, rather than an HTML file or a generic `application/octet-stream`
 | |
|   binary content.
 | |
| 
 | |
| * When ``as_attachment=True`` is passed to ``FileResponse``, it sets the
 | |
|   appropriate ``Content-Disposition`` header and that tells Web browsers to
 | |
|   pop-up a dialog box prompting/confirming how to handle the document even if a
 | |
|   default is set on the machine. If the ``as_attachment`` parameter is omitted,
 | |
|   browsers will handle the PDF using whatever program/plugin they've been
 | |
|   configured to use for PDFs.
 | |
| 
 | |
| * You can provide an arbitrary ``filename`` parameter. It'll be used by browsers
 | |
|   in the "Save as..." dialog.
 | |
| 
 | |
| * Hooking into the ReportLab API is easy: The same buffer passed as the first
 | |
|   argument to ``canvas.Canvas`` can be fed to the
 | |
|   :class:`~django.http.FileResponse` class.
 | |
| 
 | |
| * Note that all subsequent PDF-generation methods are called on the PDF
 | |
|   object (in this case, ``p``) -- not on ``buffer``.
 | |
| 
 | |
| * Finally, it's important to call ``showPage()`` and ``save()`` on the PDF
 | |
|   file.
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     ReportLab is not thread-safe. Some of our users have reported odd issues
 | |
|     with building PDF-generating Django views that are accessed by many people
 | |
|     at the same time.
 | |
| 
 | |
| Other formats
 | |
| =============
 | |
| 
 | |
| Notice that there isn't a lot in these examples that's PDF-specific -- just the
 | |
| bits using ``reportlab``. You can use a similar technique to generate any
 | |
| arbitrary format that you can find a Python library for. Also see
 | |
| :doc:`/howto/outputting-csv` for another example and some techniques you can use
 | |
| when generated text-based formats.
 | |
| 
 | |
| .. seealso::
 | |
| 
 | |
|     Django Packages provides a `comparison of packages
 | |
|     <https://djangopackages.org/grids/g/pdf/>`_ that help generate PDF files
 | |
|     from Django.
 |