$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
[Django] Generating PDF with PDFForm
Search
Sébastien Fievet
April 16, 2011
Programming
0
86
[Django] Generating PDF with PDFForm
Sébastien Fievet
April 16, 2011
Tweet
Share
More Decks by Sébastien Fievet
See All by Sébastien Fievet
Introduction to Flask
zyegfryed
0
62
Django Round-Up – Meetup Django CH #28
zyegfryed
0
60
Django Round-Up – Meetup Django CH #25
zyegfryed
0
55
Django Round-Up – Meetup Django CH #23
zyegfryed
0
51
Django Round-Up – Meetup Django CH #21
zyegfryed
0
68
Django Round-Up – Meetup Django CH #20
zyegfryed
0
69
Django Round-Up – Meetup Django CH #19
zyegfryed
2
87
[Django] URL prefix with runserver
zyegfryed
0
1.4k
[Django] RESTful API
zyegfryed
1
220
Other Decks in Programming
See All in Programming
分散DBって何者なんだ... Spannerから学ぶRDBとの違い
iwashi623
0
170
TypeScriptで設計する 堅牢さとUXを両立した非同期ワークフローの実現
moeka__c
6
2.9k
認証・認可の基本を学ぼう前編
kouyuume
0
150
20 years of Symfony, what's next?
fabpot
2
310
Herb to ReActionView: A New Foundation for the View Layer @ San Francisco Ruby Conference 2025
marcoroth
0
240
AWS CDKの推しポイントN選
akihisaikeda
1
240
Microservices rules: What good looks like
cer
PRO
0
540
ViewファーストなRailsアプリ開発のたのしさ
sugiwe
0
390
AIコーディングエージェント(NotebookLM)
kondai24
0
120
AIコーディングエージェント(Manus)
kondai24
0
120
ソフトウェア設計の課題・原則・実践技法
masuda220
PRO
24
21k
大体よく分かるscala.collection.immutable.HashMap ~ Compressed Hash-Array Mapped Prefix-tree (CHAMP) ~
matsu_chara
1
210
Featured
See All Featured
Context Engineering - Making Every Token Count
addyosmani
9
460
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Typedesign – Prime Four
hannesfritz
42
2.9k
How STYLIGHT went responsive
nonsquared
100
5.9k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.3k
Navigating Team Friction
lara
191
16k
Why Our Code Smells
bkeepers
PRO
340
57k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Writing Fast Ruby
sferik
630
62k
[RailsConf 2023] Rails as a piece of cake
palkan
58
6.1k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
700
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.3k
Transcript
Generating PDF with PDFForm Sébastien Fievet Djangocong Marseille April 16,
2011
Case study: outputting “simple” PDFs
Simple things should remain simple
Focus on skills
Designer == templating
Developper == rendering
The solution ?
None
None
1
pip install fdfgen
from fdfgen import forge_fdf def fill_form(fields, src, pdftk_bin): ... fdf_stream
= forge_fdf(fdf_data_strings=fields) ...
Issue
Issue Breaks on accentuated character
“ ” Fork it, fix it, contribute it. -- a
DVCS convinced guy
2
aptitude install pdftk
pdftk <PDF input> dump_data_fields
pdftk <PDF input> fill_form <FDF file> output <PDF output> flatten
import subprocess ... def fill_form(fields, src, pdftk_bin): ... cmd =
' '.join([pdftk_bin, src, 'fill_form', '-', 'output', '-', 'flatten']) try: process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) return process.communicate(input=fdf_stream) except OSError, e: return None, e
But...
But... utf8 support broken on Ubuntu 10.10(binary package, v1.41)
But... utf8 support broken on Ubuntu 10.10(binary package, v1.41) Use
the source luke (v1.44)
But... utf8 support broken on Ubuntu 10.10(binary package, v1.41) Use
the source luke (v1.44) wget && make && make install
3
Django template engine == The challenge
Template loading
Template loading PDFs are binary file
Template loading PDFs are binary file We don't care about
the file content
Template loading PDFs are binary file We don't care about
the file content But we ALWAYS need the template path
import codecs from django.template.loader import find_template def get_template(template_name): def strict_errors(exception):
raise exception def fake_strict_errors(exception): return (u'', -1) codecs.register_error('strict', fake_strict_errors) template, origin = find_template(template_name) codecs.register_error('strict', strict_errors) return template
from django.template import loader, Template ... def get_template_from_string(source, origin=None, name=None):
if name and name.endswith('.pdf'): return PdfTemplate('pdf', origin, name) return Template(source, origin, name) loader.get_template_from_string = get_template_from_string
Template origin * Paranoiac mode
Template origin TEMPLATE_DEBUG = True * Paranoiac mode
Template origin TEMPLATE_DEBUG = True Or monkey-patch make_origin * *
Paranoiac mode
Template rendering
Template rendering Custom rendering method Leveraging pdftk and FDFGen Use
a dedicated Template class
from django.template import Template ... class PdfTemplate(Template): def __init__(self, template_string,
origin=None, name='<Unknown Template>'): self.origin = origin def render(self, context): context = context.items() output, err = fill_form(context, self.origin.name) if err: raise PdfTemplateError(err) return output
https://gist.github.com/918403
4
Usage
from django.http import HttpResponse from pdf import get_template def pdf_view(request,
template_name='pdf/awesome.pdf'): context = { 'foo': 'bar', 'bar': 'baz', 'awesome': True, 'user': request.user, } response = HttpResponse(mimetype='application/pdf') response['Content-Disposition'] = 'attachment; filename=awesome.pdf' template = get_template(template_name) response.write(template.render(context)) return response
Demo
Questions?