Django - PISA: Adicionando imagens à saída PDF
-
24-09-2019 - |
Pergunta
Estou usando um exemplo padrão da web (http://www.20seven.org/journal/2008/11/pdf-generation-with-pisa-in-django.html) para converter uma exibição / modelo de django em um PDF.
Existe uma maneira "fácil" de incluir imagens (de um URL ou de uma referência no servidor) no modelo para que elas apareçam no PDF?
Solução
Eu tenho as imagens funcionando. O código é o seguinte:
from django.http import HttpResponse
from django.template.loader import render_to_string
from django.template import RequestContext
from django.conf import settings
import ho.pisa as pisa
import cStringIO as StringIO
import cgi
import os
def dm_monthly(request, year, month):
html = render_to_string('reports/dmmonthly.html', { 'pagesize' : 'A4', }, context_instance=RequestContext(request))
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), dest=result, link_callback=fetch_resources )
if not pdf.err:
return HttpResponse(result.getvalue(), mimetype='application/pdf')
return HttpResponse('Gremlins ate your pdf! %s' % cgi.escape(html))
def fetch_resources(uri, rel):
path = os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ""))
return path
Isso foi levado liberalmente de http://groups.google.com/group/xhtml2pdf/browse_thread/thread/4cf4e5e0f4c99f55
Outras dicas
Não consegui que as imagens aparecessem, apesar de tentar todas as soluções que pudesse encontrar no Google. Mas esse caldo funcionou para mim como a versão da linha de comando do PISA exibe imagens OK:
from tempfile import mkstemp
# write html to a temporary file
# can used NamedTemporaryFile if using python 2.6+
fid, fname = mkstemp(dir='/tmp')
f = open(fname, 'w+b')
f.write(html)
f.close()
# now create pdf from the html
cmd = 'xhtml2pdf "%s"' % fname
os.system(cmd)
os.unlink(fname)
# get the content of the pdf
filename = fname+'.pdf'
pdf = open(filename, 'r')
content = pdf.read()
pdf.close()
os.unlink(pdf.name)
# return content
response = HttpResponse(content, mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=draft.pdf'
Isso funcionou onde as imagens tinham um URL ou o nome do caminho completo, por exemplo.
<img src="/home/django/project/site_media/css/output/images/logo.jpg" />
<img src="http://www.mysite.com/css/output/images/logo.jpg" />
def render_to_pdf( template_src, context_dict):
template = get_template(template_src)
context = Context(context_dict)
html = template.render(context)
result = StringIO.StringIO()
if page has an image.something:
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), dest=result, link_callback=fetch_resources)
else no image.something :
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")),result)
if not pdf.err:
return HttpResponse(result.getvalue(), mimetype='examination_report/pdf')
return HttpResponse('We had some errors<pre>%s</pre>' % escape(html))
def fetch_resources(uri, rel):
if os.sep == '\\': # deal with windows and wrong slashes
uri2 = os.sep.join(uri.split('/'))
else:# else, just add the untouched path.
uri2 = uri
path = '%s%s' % (settings.SITE_ROOT, uri2)
return path
Todo o código acima não funcionou para mim. No final, consegui funcionar colocando o procedimento get_full_path. Então, o código final se parece com este
def render_to_pdf( template_src, context_dict):
now = datetime.now()
filename = now.strftime('%Y-%m-%d') + '.pdf'
template = get_template(template_src)
context = Context(context_dict)
html = template.render(context)
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")),result, path=path)
if not pdf.err:
response = HttpResponse(result.getvalue(), mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename="'+filename+'"'
return response
return HttpResponse('We had some errors<pre>%s</pre>' % escape(html))
def get_full_path_x(request):
full_path = ('http', ('', 's')[request.is_secure()], '://',
request.META['HTTP_HOST'], request.path)
return ''.join(full_path)
A linha de código a seguir na versão html e django = 2.0 funciona para mim.
<img src="{{company.logo.path}}" height="100px">
Você sempre pode adicionar as imagens depois com o ITEXT/ISHARP.
Você também pode converter a imagem em base64.
http://www.motobit.com/util/base64-decoder-encoder.asp
Convertendo para base64 Você nunca terá problemas com links de imagem.