33 votes

django - pisa : ajout d'images à la sortie du PDF

J'utilise un exemple standard du web ( http://www.20seven.org/journal/2008/11/pdf-generation-with-pisa-in-django.html ) pour convertir une vue / un modèle django en PDF.

Existe-t-il un moyen "simple" d'inclure des images (à partir d'une URL ou d'une référence sur le serveur) dans le modèle afin qu'elles apparaissent sur le PDF ?

2 votes

Lien mort - c'est ici : 20seven.org/journal/2008/11/11/…

35voto

jduncan Points 177

J'ai réussi à faire fonctionner les images. Le code est le suivant :

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

C'est tiré librement de http://groups.google.com/group/xhtml2pdf/browse_thread/thread/4cf4e5e0f4c99f55

0 votes

Fyi pour les non-utilisateurs de Django, MEDIA_ROOT est le répertoire où se trouve physiquement le document html que vous convertissez et MEDIA_URL est le http-friendly de cet emplacement (par exemple, pour un fichier html local : MEDIA_URL = 'file:///' + MEDIA_ROOT ). Sinon, il s'agit d'une bonne solution générale !

0 votes

Et si j'utilise S3 ?

2voto

PhoebeB Points 2862

Je n'ai pas réussi à faire apparaître les images malgré toutes les solutions que j'ai pu trouver sur Google. Mais cette astuce a fonctionné pour moi, car la version en ligne de commande de pisa affiche les images sans problème :

    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'

Cela fonctionnait lorsque les images avaient soit une url, soit le nom complet du chemin, par exemple.

<img src="/home/django/project/site_media/css/output/images/logo.jpg" />

<img src="http://www.mysite.com/css/output/images/logo.jpg" />

2voto

Krazzzeee Points 46
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

2voto

vinod philip Points 11

Tout le code ci-dessus n'a pas fonctionné pour moi. Finalement, j'ai réussi à le faire fonctionner en utilisant la procédure get_full_path. Donc le code final ressemble à ceci

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)

1voto

Lara Points 197

Vous pouvez également convertir l'image en base64.

http://www.motobit.com/util/base64-decoder-encoder.asp

En convertissant en base64, vous n'aurez jamais de problèmes avec les liens d'images.

2 votes

Oui, les images peuvent être converties en base64. Veuillez ajouter un exemple sur la façon de les placer dans le pdf.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X