Is there a way to generate pdf containing non-ascii symbols with pisa from django template?
Asked Answered
F

6

21

I'm trying to generate a pdf from template using this snippet:

def write_pdf(template_src, context_dict):
    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)
    if not pdf.err:
        return http.HttpResponse(result.getvalue(), mimetype='application/pdf')
    except Exception('PDF error')

All non-latin symbols are not showing correctly, the template and view are saved using utf-8 encoding.

I've tried saving view as ANSI and then to user unicode(html,"UTF-8"), but it throws TypeError.

Also I thought that maybe it's because the default fonts somehow do not support utf-8 so according to pisa documentation I tried to set fontface in template body in style section.

That still gave no results.

Does any one have some ideas how to solve this issue?

Frantic answered 28/10, 2009 at 13:26 Comment(0)
P
32

This does work for me:

pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), result, encoding='UTF-8')
Pippo answered 24/11, 2009 at 10:57 Comment(1)
I also required to add <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> to template for non-ascii characters to show properlyLochner
H
4

Try replacing

pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), result)

with

pdf = pisa.pisaDocument(StringIO.StringIO(html), result, encoding='UTF-8')

Or checkout this answer to html to pdf for a Django site?

Here answered 28/10, 2009 at 13:37 Comment(3)
after replaceing got pdf full of unreadable data, checked the solution, the method doesn't differ much from what i use, but i still tested it, with html.encode("ISO-8859-1") it throws: "'latin-1' codec can't encode character u'\ufeff' in position 0: ordinal not in range(256)" with encode("UTF-8") it returns pdf but the same as i hve got previously - non-ascii symbols are still not rendered properly.Frantic
@Frantic have you found a solution?Landlordism
exactly adding this: encoding='UTF-8' solved my problem with encoding polish charactersVelarde
S
2

You need to modify your django template. Add a new font face in the stylesheet that will link to a font file with characters used in your document. And that font file must be accessible from your server (under Ubuntu you can find files with fonts in /usr/share/fonts/truetype/ directory). For example:

@font-face {
  font-family: DejaMono; 
  src: url(font/DejaVuSansMono.ttf);
}

Then if you have next HTML code:

<div>Some non-latin characters</div>

you can display that text in DejaMono font with this CSS rule:

div { font-family: DejaMono; }

This works for me when I generate PDF documents with cyrillic characters.

Scandic answered 27/1, 2010 at 13:11 Comment(0)
S
1

I faced the same problem with cyrillic characters.

The solution contained two steps: 1. Point out the font file in your HTML file

<style type="text/css">
@font-face {
  font-family: Arial; src: url("files/arial.ttf");
}
body {
  font-family: Arial;
}
</style>

2. Give "pisa" root path (so that it find font file by relative path) in my case it was something like this

pdf = pisa.pisaDocument(html, result, path=PATH_TO_DJANGO_PROJECT)

because fonts were placed at PATH_TO_DJANGO_PROJECT/files/arial.ttf

Soloman answered 18/10, 2017 at 23:25 Comment(0)
P
1

I am using xhtml2pdf version 0.2.4 I faced the same issue and I was able to resolve using this encoding:

def render_to_pdf(template_src, context_dict={}):
    template = get_template(template_src)
    html = template.render(context_dict)
    result = BytesIO()

    # PDF
    pdf = pisa.pisaDocument(BytesIO(html.encode("utf-8")), result)
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type='application/pdf')
    return None

Then in my views, I have defined like:

def download_pdf(request, pk):
item = get_object_or_404(object, id=pk)
if item:
    context ={
        'item': item
    }
    template_name = 'template.html'
    pdf = render_to_pdf(template_name, context)
    return HttpResponse(pdf, content_type='application/pdf')

else:
    messages.info(request, 'Item not found')
    return redirect('home')

My HTML:

{% load static %}
{% load humanize %}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="icon" type="image/gif" href="{% static 'images/profile.png' %}" />
    <title>{{ item.scientific_name}}</title>
    <link rel="stylesheet" href="{% static 'style/Bootstrap/css/bootstrap.min.css' %}">

   <style>
    @page {
        size: letter;
        margin: 2cm;

        @frame footer_frame {
            /* Another static Frame */
            -pdf-frame-content: footer_content;
            left: 50pt;
            width: 512pt;
            top: 760pt;
            height: 50px;
        }

        table {
            -pdf-keep-with-next: true;
        }
    }

    ul {
        list-style-type: none;
    }

    ul li span {
        font-weight: bold;
    }
</style>
Pounds answered 5/5, 2020 at 12:2 Comment(0)
H
0

If you are calling createPDF instead of the pisaDocument method, you can use

pisa.CreatePDF(html.encode('UTF-8'), response, link_callback=fetch_resources, encoding='UTF-8')
Herodias answered 27/7, 2010 at 10:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.