Skip to content

Instantly share code, notes, and snippets.

@ryllada
Created October 11, 2016 11:38
Show Gist options
  • Save ryllada/d9cb322c15161c5ca24ca21a936fdb75 to your computer and use it in GitHub Desktop.
Save ryllada/d9cb322c15161c5ca24ca21a936fdb75 to your computer and use it in GitHub Desktop.
# -*- encoding: utf-8 -*-
from django.template.loader import get_template
from django.template import Context
from django.conf import settings
import cStringIO as StringIO
import ho.pisa as pisa
import datetime
import os
import subprocess
WK_OPCIONES_MULTIPLES_ENTRADAS_A3 = {
'--margin-bottom ': '0',
'--margin-left ': '0',
'--margin-right ': '0',
'--margin-top ': '0',
'--orientation ': 'Portrait',
'--dpi ': '300',
'--disable-smart-shrinking': '',
'--page-size ': 'A3',
'--footer-center ': u""""[page] / [topage]\"""",
'-q': '',
}
WK_OPCIONES_MULTIPLES_ENTRADAS_186x80 = {
'--page-width ': '186mm',
'--page-height ': '80mm',
'--dpi ': '300',
'--margin-bottom ': '0',
'--margin-left ': '0',
'--margin-right ': '0',
'--margin-top ': '0',
'--disable-smart-shrinking': '',
'-q': '',
}
WK_OPCIONES_ENTRADA_EVENTO_A4 = {
'--margin-bottom ': '0',
'--margin-left ': '0',
'--margin-right ': '0',
'--margin-top ': '0',
'--dpi ': '300',
'--disable-smart-shrinking': '',
'--page-size ': 'A4',
'-q': '',
}
class PDFHandler(object):
""" Se encarga de crear ficheros PDF temporales en el sistema de ficheros
local, para luego poder usar en cualquier lugar, por ejemplo como respuesta
de una vista, como creación de un adjunto de un correo.
Recordar que es mejor que se lancen excepciones desde aquí, y se manipulen
en la capa superior (vistas generalmente).
"""
contexto = {}
wk_options = {'--margin-bottom ': '0',
'--margin-left ': '0',
'--margin-right ': '0',
'--margin-top ': '0',
'--dpi ': '96',
'--disable-smart-shrinking': '',
'-q': '',
}
# Ins
template_path = None
template = None
nombre_base = u''
# Outs
pdf_file_path = None
rendered_filenames = () # Lista de absolute paths de ficheros renderizados
def __init__(self, *args, **kwargs):
for key, value in kwargs.iteritems():
setattr(self, key, value)
super(PDFHandler, self).__init__(*args, **kwargs)
return
# Renders privados
def _render_via_wkhtml(self, **kwargs):
self.nombre_base += u'%s' % (
unicode(datetime.datetime.now()).replace(' ', '_'), )
_filename_in = os.path.join(
settings.TEMP_ROOT, '%s.html' % self.nombre_base)
_filein = open(_filename_in, 'w')
_filein.write(self.template)
_filein.close()
self.rendered_filenames += (_filename_in, )
# PDF
_cmd_tuple = ('wkhtmltopdf',)
for item, value in self.wk_options.iteritems():
_cmd_tuple += (item + value, )
_filename_out = os.path.join(
settings.TEMP_ROOT, '%s.pdf' % self.nombre_base)
_cmd_tuple += (_filename_in, _filename_out, )
if settings.DEBUG:
print 'DEBUG;', ' '.join(_cmd_tuple)
_out = subprocess.call(' '.join(_cmd_tuple), shell=True, close_fds=True)
if _out != 0:
raise RuntimeError(
u"""Salida del wkhtmltopdf: %d - filenamein:
%s - filenameout: %s - comando: %s""" % (
_out, _filename_in, _filename_out, _cmd_tuple, )
)
_fileout = open(_filename_out) # Test
_fileout.close()
self.pdf_file_path = _filename_out
self.rendered_filenames += (_filename_out, )
return
def _render_template(self, template, contexto_dict=None, contexto=None):
_contexto = contexto or Context(contexto_dict)
self.template = get_template(template)
self.template = self.template.render(_contexto)
self.template = self.template.encode("UTF-8")
# Métodos públicos
def clear(self):
# Elimina los ficheros creados
for item in self.rendered_filenames:
try:
os.unlink(item)
except OSError:
pass
self.rendered_filenames = ()
return
def render_wkhtmlpdf(self, template, contexto_dict=None, contexto=None):
self._render_template(template, contexto_dict, contexto)
self._render_via_wkhtml()
return
def render_pisa(self, template, contexto_dict=None, contexto=None):
from cgi import escape
result = StringIO.StringIO()
self._render_template(template, contexto_dict, contexto)
_pdf = pisa.pisaDocument(
StringIO.StringIO(self.template), result,
link_callback=self._fetch_resources_pisa, encoding='UTF-8')
self.result = result.getvalue()
return
def _fetch_resources_pisa(self, uri, rel):
return settings.MEDIA_ROOT + uri.replace(settings.MEDIA_URL, "/")
# Customs
def render_entrada_evento(self, entrada, contexto={}, debug_local=False):
self.contexto = Context(contexto)
self.contexto['entrada'] = entrada
self.contexto['sesion'] = entrada.recibo.inscripcion.tarifa.sesion
self.contexto['MEDIA_ROOT'] = settings.MEDIA_ROOT
self.contexto['MEDIA_URL'] = settings.MEDIA_URL
self.contexto['absolute_static_paths'] = not debug_local
self.template_path = 'eventos/pdf/entrada_a4.html'
self.template = get_template(self.template_path)
self.template = self.template.render(self.contexto)
self.template = self.template.encode("UTF-8")
if debug_local:
return
self.wk_options.update(WK_OPCIONES_ENTRADA_EVENTO_A4)
self._render_via_wkhtml()
return
# Múltiples: Como norma no se debería usar en vistas
def render_multiples_entradas_186x80(self, query, contexto={},
debug_local=False, **kwargs):
self.contexto = Context(contexto)
self.contexto['object_list'] = query
self.template_path = kwargs['template']
if debug_local:
self.contexto['absolute_static_paths'] = False
self.contexto['MEDIA_URL'] = settings.MEDIA_URL
else:
self.contexto['absolute_static_paths'] = True
self.contexto['MEDIA_ROOT'] = settings.MEDIA_ROOT
self.template = get_template(self.template_path)
self.template = self.template.render(self.contexto)
self.template = self.template.encode("UTF-8")
self.wk_options.update(WK_OPCIONES_MULTIPLES_ENTRADAS_186x80)
self.nombre_base = kwargs['template'].replace('/', '_')
self._render_via_wkhtml()
return
def render_multiples_entradas_evento_a3(self, bloques, contexto={},
debug_local=False, **kwargs):
""" Página con bloques de diez
"""
self.contexto = Context(contexto)
try:
self.template_path = kwargs['template']
except KeyError:
self.template_path = 'eventos/pdf/entradas_multiples_a3.html'
self.contexto['bloques_entradas'] = bloques
if debug_local:
self.contexto['absolute_static_paths'] = False
self.contexto['MEDIA_URL'] = settings.MEDIA_URL
else:
self.contexto['absolute_static_paths'] = True
self.contexto['MEDIA_ROOT'] = settings.MEDIA_ROOT
self.template = get_template(self.template_path)
self.template = self.template.render(self.contexto)
self.template = self.template.encode("UTF-8")
self.wk_options = WK_OPCIONES_MULTIPLES_ENTRADAS_A3
_kwargs = {}
try:
self.nombre_base = kwargs['raiz_nombre']
except KeyError:
self.nombre_base = kwargs['template'].replace('/', '_')
self._render_via_wkhtml(**_kwargs)
return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment