django /媒体URI中XHTML2PDF编码的UTF-8必须以 / static / or / /媒体 / / / / / /媒体 /的
我正在使用 xhtml2pdf 包从 django 应用程序中的 html 模板生成 pdf 文件。 pdf 文件生成正确(没有错误),但是,我遇到了 UTF-8 编码的问题。我生成的 pdf 文件显示黑色方块,而不是特殊字符(PL 语言)。我已经浏览了几乎所有在线可用的解决方案,但没有一个有帮助。当我使用 ReportLab 并在没有模板的情况下生成 pdf 时,一切似乎都很好。 我是否在景观方面错过了一些东西?
要更新,我相信我遇到的问题实际上是在检索字体。 我添加了回调链接,并尝试在模板中使用 {% static %} 引用。但这会引发错误媒体 URI 必须以 /static/ 或 /media/ 开头
我的 html 模板
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>PDF {{obj.orderNumber}}</title>
<style>
@font-face {
font-family: "Roboto-Black";
src: url({% static "fonts/Roboto.ttf" %});
}
@font-face {
font-family: "Roboto-Regular";
src: url({% static "Roboto-Regular.ttf" %});
}
@font-face {
font-family: "Roboto-Bold";
src: url({% static "Roboto-Bold.ttf" %});
font-weight: bold;
}
body, html {
font-family: Roboto;
}
table { -pdf-keep-with-next: true; }
p { margin: 0; -pdf-keep-with-next: true; }
p.separator { -pdf-keep-with-next: false; font-size: 6pt; }
.bander{
color:brown;
font-size:13pt;
}
</style>
</head>
<body>
<img src="media/logo.jpg" style="height:60px;">
<h2> PLAN ROZKROJU ZLECENIA: </h2>
<h1 style="color:#997207;">{{obj.orderNumber}} {{obj.orderName}}</h3>
<h2> Naklad: {{obj.orderQuantity}} szt </h2>
<h4> Data utworzenia wydruku: {{obj3}} </h4>
<div>
<table class="table table-bordered" style="text-align: center; padding: 5px;" border="0.2">
<thead class="table-active">
<tr>
<th scope="col">Nazwa materialu</th>
<th scope="col">Ilosc</th>
<th scope="col">Nazwa czesci</th>
<th scope="col">Wymiar (mm)</th>
<th scope="col">Wymiar 2 (mm)</th>
</tr>
</thead>
<tbody>
{% for item in obj2 %}
<tr>
<td>{{ item.itemMaterial }}</td>
<td>{{ item.itemQuantity }} szt</td>
<td>{{ item.itemName }}</td>
{% if item.itemBander == 'OKLEJANIE 1 STR' %}
<td class="text-center"><b class="bander">*</b> {{ item.itemDimmension1 }}</td>
{% elif item.itemBander == 'OKLEJANIE 2 STR' %}
<td class="text-center"><b class="bander">*</b> {{ item.itemDimmension1 }} <b class="bander">*</b></td>
{% else %}
<td class="text-center">{{ item.itemDimmension1 }}</td>
{% endif %}
{% if item.itemBander2 == 'OKLEJANIE 1 STR' %}
<td class="text-center"><b class="bander">*</b> {{ item.itemDimmension2 }}</td>
{% elif item.itemBander2 == 'OKLEJANIE 2 STR' %}
<td class="text-center"><b class="bander">*</b> {{ item.itemDimmension2 }} <b class="bander">*</b></td>
{% else %}
<td class="text-center">{{ item.itemDimmension2 }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<p></p>
<h6><i> LEGENDA:<b class="bander">*</b> wymiar - oklejanie 1-str // <b class="bander">*</b> wymiar <b class="bander">*</b> - oklejanie 2 str</i></h6>
</body>
</html>
我的views.py
def link_callback(uri, rel):
"""
Convert HTML URIs to absolute system paths so xhtml2pdf can access those
resources
"""
sUrl = settings.STATIC_URL # Typically /static/
sRoot = settings.STATIC_ROOT # Typically /home/userX/project_static/
mUrl = settings.MEDIA_URL # Typically /media/
mRoot = settings.MEDIA_ROOT # Typically /home/userX/project_static/media/
bRoot = settings.BASE_DIR # Project's base directory
if uri.startswith(mUrl):
path = os.path.join(mRoot, uri.replace(mUrl, ""))
elif uri.startswith(sUrl):
path = os.path.join(sRoot, uri.replace(sUrl, ""))
else:
return os.path.join(bRoot, '../', uri)
# make sure that file exists
if not os.path.isfile(path):
raise Exception(
'media URI must start with %s or %s' % (sUrl, mUrl)
)
return path
# PDF VIEWS#
@login_required
@admin_or_manager_required
def render_pdf_view(request, pk):
template_path = "orders/pdf.html"
obj = get_object_or_404(Order, pk=pk)
obj2 = Item.objects.filter(itemOrder=obj)
obj3 = datetime.now()
context = {"obj": obj, "obj2": obj2, "obj3": obj3}
response = HttpResponse(content_type="application/pdf")
response["Content-Disposition"] = 'filename="file.pdf"'
template = get_template(template_path)
html = template.render(context)
pisa_status = pisa.CreatePDF(html.encode("UTF-8"), response , encoding='UTF-8', link_callback=link_callback)
if pisa_status.err:
return HttpResponse("We had some errors <pre>" + html + "</pre>")
return response
我的settings.py
STATIC_URL = "/static/"
STATICFILES_DIRS = [
os.path.join(BASE_DIR, ""),
os.path.join(BASE_DIR, "static")
]
STATIC_ROOT = "static_root"
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
I am using xhtml2pdf package to generate a pdf file from an html template in my django application. The pdf file generates correctly (no errors), however, I have encountered a problem with UTF-8 encoding. My generated pdf file, instead of special charactes (PL language), shows black squares. I have gone through almost all solutions available online, but none of them helped. When I am using ReportLab and generate pdf without a template, all seems to be okay.
Am I missing something perhaps on the views side?
To update, I believe the problem I have is really in retrieving the font.
I have added the callback_link, and tried to used {% static %} reference in my template. But this throws an error media URI must start with /static/ or /media/
My html template
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>PDF {{obj.orderNumber}}</title>
<style>
@font-face {
font-family: "Roboto-Black";
src: url({% static "fonts/Roboto.ttf" %});
}
@font-face {
font-family: "Roboto-Regular";
src: url({% static "Roboto-Regular.ttf" %});
}
@font-face {
font-family: "Roboto-Bold";
src: url({% static "Roboto-Bold.ttf" %});
font-weight: bold;
}
body, html {
font-family: Roboto;
}
table { -pdf-keep-with-next: true; }
p { margin: 0; -pdf-keep-with-next: true; }
p.separator { -pdf-keep-with-next: false; font-size: 6pt; }
.bander{
color:brown;
font-size:13pt;
}
</style>
</head>
<body>
<img src="media/logo.jpg" style="height:60px;">
<h2> PLAN ROZKROJU ZLECENIA: </h2>
<h1 style="color:#997207;">{{obj.orderNumber}} {{obj.orderName}}</h3>
<h2> Naklad: {{obj.orderQuantity}} szt </h2>
<h4> Data utworzenia wydruku: {{obj3}} </h4>
<div>
<table class="table table-bordered" style="text-align: center; padding: 5px;" border="0.2">
<thead class="table-active">
<tr>
<th scope="col">Nazwa materialu</th>
<th scope="col">Ilosc</th>
<th scope="col">Nazwa czesci</th>
<th scope="col">Wymiar (mm)</th>
<th scope="col">Wymiar 2 (mm)</th>
</tr>
</thead>
<tbody>
{% for item in obj2 %}
<tr>
<td>{{ item.itemMaterial }}</td>
<td>{{ item.itemQuantity }} szt</td>
<td>{{ item.itemName }}</td>
{% if item.itemBander == 'OKLEJANIE 1 STR' %}
<td class="text-center"><b class="bander">*</b> {{ item.itemDimmension1 }}</td>
{% elif item.itemBander == 'OKLEJANIE 2 STR' %}
<td class="text-center"><b class="bander">*</b> {{ item.itemDimmension1 }} <b class="bander">*</b></td>
{% else %}
<td class="text-center">{{ item.itemDimmension1 }}</td>
{% endif %}
{% if item.itemBander2 == 'OKLEJANIE 1 STR' %}
<td class="text-center"><b class="bander">*</b> {{ item.itemDimmension2 }}</td>
{% elif item.itemBander2 == 'OKLEJANIE 2 STR' %}
<td class="text-center"><b class="bander">*</b> {{ item.itemDimmension2 }} <b class="bander">*</b></td>
{% else %}
<td class="text-center">{{ item.itemDimmension2 }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<p></p>
<h6><i> LEGENDA:<b class="bander">*</b> wymiar - oklejanie 1-str // <b class="bander">*</b> wymiar <b class="bander">*</b> - oklejanie 2 str</i></h6>
</body>
</html>
My views.py
def link_callback(uri, rel):
"""
Convert HTML URIs to absolute system paths so xhtml2pdf can access those
resources
"""
sUrl = settings.STATIC_URL # Typically /static/
sRoot = settings.STATIC_ROOT # Typically /home/userX/project_static/
mUrl = settings.MEDIA_URL # Typically /media/
mRoot = settings.MEDIA_ROOT # Typically /home/userX/project_static/media/
bRoot = settings.BASE_DIR # Project's base directory
if uri.startswith(mUrl):
path = os.path.join(mRoot, uri.replace(mUrl, ""))
elif uri.startswith(sUrl):
path = os.path.join(sRoot, uri.replace(sUrl, ""))
else:
return os.path.join(bRoot, '../', uri)
# make sure that file exists
if not os.path.isfile(path):
raise Exception(
'media URI must start with %s or %s' % (sUrl, mUrl)
)
return path
# PDF VIEWS#
@login_required
@admin_or_manager_required
def render_pdf_view(request, pk):
template_path = "orders/pdf.html"
obj = get_object_or_404(Order, pk=pk)
obj2 = Item.objects.filter(itemOrder=obj)
obj3 = datetime.now()
context = {"obj": obj, "obj2": obj2, "obj3": obj3}
response = HttpResponse(content_type="application/pdf")
response["Content-Disposition"] = 'filename="file.pdf"'
template = get_template(template_path)
html = template.render(context)
pisa_status = pisa.CreatePDF(html.encode("UTF-8"), response , encoding='UTF-8', link_callback=link_callback)
if pisa_status.err:
return HttpResponse("We had some errors <pre>" + html + "</pre>")
return response
My settings.py
STATIC_URL = "/static/"
STATICFILES_DIRS = [
os.path.join(BASE_DIR, ""),
os.path.join(BASE_DIR, "static")
]
STATIC_ROOT = "static_root"
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论