Answer the question
In order to leave comments, you need to log in
Generating from HTML template to Cyrillic PDF in Django 2.x (xhtml2pdf)?
Hello.
I ran into a problem that occurs very often in Google, but not a single solution has worked, or refers to Python 2.7.x. That's actually why I'm asking here...
■■ ■ ■■ ■ ■■ ■ ■ ■
), but everything is ok with the Latin alphabet. # app/utils.py
from xhtml2pdf import pisa
def render_to_pdf(template_src, context_dict):
result = BytesIO()
template = render_to_string(template_src, context_dict)
pdf = pisa.pisaDocument(BytesIO(template.encode('UTF-8')), result)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
# app/views.py
from .utils import render_to_pdf
class GeneratePDF(LoginRequiredMixin, View):
def get(self, request, order_type, order_id):
"""
Generate PDF from HTML template
"""
try:
order = BasicOrder.objects.get(
id=order_id, user=request.user.id, status__in=[1, 2]
)
except BasicOrder.DoesNotExist:
return HttpResponse(status=404)
context = {
'order_id': order.id
}
template = 'pdf/simple.html'
pdf = render_to_pdf(template, context)
if pdf:
filename = 'order_{}_{}.pdf'.format(order_type, order_id)
content = 'inline; filename="{}"'.format(filename)
if request.GET.get('save_to_file') == 'true':
content = 'attachment; filename="{}"'.format(filename)
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = content
return response
return HttpResponse(status=404)
templates/pdf/simple.html
(saved in UTF-8):<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Заказ № {{ order_id }}</title>
<style type="text/css">
@page {
size: letter landscape;
border: 1px solid #999999;
margin: .4cm;
}
@font-face {
font-family: 'OpenSansRegular';
src: url("/static/fonts/OpenSans/OpenSans-Regular.ttf");
}
body {
font-family: 'OpenSansRegular', sans-serif;
font-size: 16px;
}
.container {
padding: .4cm;
}
</style>
</head>
<body>
<div class="container">
Заказ № {{ order_id }}
</div>
</body>
</html>
Answer the question
In order to leave comments, you need to log in
The renderer can't load links itself, so it can't get the /static/fonts/OpenSans/OpenSans-Regular.ttf font. The pisaDocument function has a link_callback parameter, to which you can pass a function that converts http addresses to local paths. For example this one:
def fetch_pdf_resources(uri, rel):
if uri.find(settings.MEDIA_URL) != -1:
path = os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ''))
elif uri.find(settings.STATIC_URL) != -1:
path = os.path.join(settings.STATIC_ROOT, uri.replace(settings.STATIC_URL, ''))
else:
path = None
return path
pdf = pisa.pisaDocument(BytesIO(template.encode('UTF-8')), result,
encoding='utf-8',
link_callback=fetch_pdf_resources)
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question