Skip to content

Instantly share code, notes, and snippets.

@cega
Forked from zyegfryed/pdf.py
Created May 18, 2016 12:52
Show Gist options
  • Save cega/1f56641f85e6cfd6fbc02f9e3237d9b9 to your computer and use it in GitHub Desktop.
Save cega/1f56641f85e6cfd6fbc02f9e3237d9b9 to your computer and use it in GitHub Desktop.
Outputting PDFs with Django and FDFgen
# -*- coding: utf-8 -*-
import codecs
import subprocess
from fdfgen import forge_fdf
from django.template import Template, loader
from django.template.loader import find_template, LoaderOrigin
class PdfTemplateError(Exception):
pass
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 = self.fill_form(context, self.origin.name)
if err:
raise PdfTemplateError(err)
return output
def fill_form(self, fields, src, pdftk_bin=None):
if pdftk_bin is None:
from django.conf import settings
assert hasattr(settings, 'PDFTK_BIN'), "PDF generation requires pdftk (http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/). Edit your PDFTK_BIN settings accordingly."
pdftk_bin = settings.PDFTK_BIN
fdf_stream = forge_fdf(fdf_data_strings=fields)
cmd = [
pdftk_bin,
src,
'fill_form',
'-',
'output',
'-',
'flatten',
]
cmd = ' '.join(cmd)
try:
process = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, shell=True)
return process.communicate(input=fdf_stream)
except OSError:
return None
def get_template_from_string(source, origin=None, name=None):
"""
Returns a compiled Template object for the given template code,
handling template inheritance recursively.
"""
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
def make_origin(display_name, loader, name, dirs):
# Always return an Origin object, because PDFTemplate need it to render
# the PDF Form file.
return LoaderOrigin(display_name, loader, name, dirs)
loader.make_origin = make_origin
def get_template(template_name):
"""
Returns a compiled Template object for the given template name,
handling template inheritance recursively.
"""
def strict_errors(exception):
raise exception
def fake_strict_errors(exception):
return (u'', -1)
# Loading hacks
# Ignore UnicodeError, due to PDF file read
codecs.register_error('strict', fake_strict_errors)
# --//--
template, origin = find_template(template_name)
# Loading hacks
codecs.register_error('strict', strict_errors)
# --//--
return template
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from django.utils.translation import ugettext as _
from pdf import get_template
def ticket_print(request, template_name='pdf_form/pdf/foobar.pdf', **kwargs):
context = {
'foo': 'bar',
'bar': _('baz'),
}
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = \
'attachment; filename=foobar.pdf'
template = get_template(template_name)
response.write(template.render(context))
return response
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment