Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django-Weasyprint image issue

As it says in the docs page, I defined a img tag in my html file as follows:

<img src='{% static 'image.png' %}'/>

This url exists in the server and I even made a different view with a http response and the image is displayed just fine. Here is the code for both views:

The pdf-weasyprint view:

def card_view(request):
    template = loader.get_template('card.html')
    context = {'sample': None
               }
    html = template.render(RequestContext(request, context))
    response = HttpResponse(mimetype='application/pdf')
    HTML(string=html).write_pdf(response)
    return response

The html view:

def card_view2(request):
    context = {'sample': None,
               }
    return render_to_response('card.html', context, 
                              context_instance=RequestContext(request))

I thought the default url fetcher was supposed to find and render the image (it's a png - so no format issue should be involved) Any ideas? Any help would be appreciated!!

like image 567
Alvaro Avatar asked Oct 01 '13 16:10

Alvaro


2 Answers

Here it is a URL fetcher which reads (image) files locally, without performing an HTTP request:

from weasyprint import HTML, CSS, default_url_fetcher
import mimetypes

def weasyprint_local_fetcher(url):
    if url.startswith('local://'):
        filepath = url[8:]
        with open(filepath, 'rb') as f:
            file_data = f.read()
        return {
            'string': file_data,
            'mime_type': mimetypes.guess_type(filepath)[0],
        }
    return default_url_fetcher(url)

In order to use it, use the local:// scheme in your URLs, for example:

<img src="local://myapp/static/images/image.svg" />

Then, pass the fetcher to the HTML __init__ method:

html = HTML(
    string=html_string,
    url_fetcher=weasyprint_local_fetcher,
)
like image 85
Luca Avatar answered Sep 30 '22 02:09

Luca


What exactly is the issue? Do you get anything in the logs? (You may need to configure logging if your server does not log stderr.) What does the generated HTML look like?

I’d really need answers to the above to confirm, but my guess is that the image’s URL is relative, but with HTML(string=...) WeasyPrint has no idea of what is the base URL. Try something like this. (I’m not sure of the Django details.)

HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(response)

This will make a real HTTP request on your app, which may deadlock on a single-threaded server. (I think the development server defaults to a single thread.)

To avoid that and the cost of going through the network, you may want to look into writing a custom "URL fetcher". It could be anywhere from specialized to just this one image, to a full Django equivalent of Flask-WeasyPrint.

like image 45
Simon Sapin Avatar answered Sep 30 '22 02:09

Simon Sapin