访问相关网址时,会显示一个html网页。我需要以编程方式将此html页面保存到服务器上的pdf文件中。
views.py
class PdfView(DetailView):
model = TheModel
template_name = 'pdf.html'
urls.py
urlpatterns = [
url(
r'^(?P<pk>[0-9]+)/$',
PdfDataView.as_view(),
name='pdf-data',
),
]
答案 0 :(得分:1)
尝试以下方法。虽然它通过响应向最终用户提供服务文件,但是将其修改为在服务器上写入文件应该很容易:
功能视图:
def pdf_sticker(request, pk):
spot = get_object_or_404(Spot, pk=pk)
if spot.is_certificated:
pdf, result = render_to_pdf(
'www/pdf_sticker.html',
{
'pass_smth': 'needed_in_render',
'MEDIA_ROOT': settings.MEDIA_ROOT,
'STATIC_ROOT': settings.STATICFILES_DIRS[0],
'pagesize': 'A6',
}
)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return HttpResponse('We had some errors')
else:
raise Http404
辅助方法:
from io import StringIO, BytesIO
from xhtml2pdf import pisa
from django.template.loader import get_template
def render_to_pdf(template_src, context_dict):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(
StringIO(html),
dest=result,
encoding='UTF-8'
)
return pdf, result
模板:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Sticker for certificated spot</title>
<style type="text/css">
@font-face {
font-family: "Lobster";
src: url("{{ STATIC_ROOT }}/font/Lobster-32.ttf");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "Lato";
src: url("{{ STATIC_ROOT }}/font/Lato-Hairline.ttf");
font-weight: 100;
font-style: thin;
}
@font-face {
font-family: "Nobile";
src: url("{{ STATIC_ROOT }}/font/Nobile-34.ttf");
font-weight: normal;
font-style: normal;
}
@page {
size: {{ pagesize }};
margin: 0.5cm;
}
</style>
</head>
<body>
<center>
<img src="{{ STATIC_ROOT }}/{{ SPOT_PROJECT_NAME }}/certificate.png" height="260px">
<p style="font-family:Lobster;">
<span style="font-size:60px;">
{% settings_value "SPOT_PROJECT_SUBJECT" %}<br>
</span>
<span style=" font-size:32px;">
friendly spot!
</span>
<br>
<table>
<tr>
<td colspan=2>
<img src="http://{{BASE_HOST}}{% url 'www:qrencode_link' pk=spot.pk size=4 %}">
</td>
</tr>
<tr>
<td colspan=2 height=5></td>
</tr>
<tr>
<td colspan=2>
<span style="font-family:Nobile; font-size:15px;">
Powered by: <img src="{{ STATIC_ROOT }}/{{ SPOT_PROJECT_NAME }}/logo.png" height="50px"> </span>
<span style="font-family:Lobster; font-size:25px;">
{{ SPOT_PROJECT_NAME }}
</span>
</td>
</tr>
</table>
</p>
</center>
</body>
</html>
为Python 3.6,Django 2.0工作。
图书馆版本:
Django==2.0.2
xhtml2pdf==0.2b1
http://xhtml2pdf.readthedocs.io/en/latest/usage.html#using-with-python-standalone
答案 1 :(得分:1)
以下解决方案在将HTTP响应提供给浏览器之前,在HTTP请求期间保存网页的pdf版本。
我使用了weasyprint,因为它设法开箱即用地处理unicode字符。
<强> views.py 强>
from weasyprint import HTML
class PdfView(DetailView):
model = TheModel
template_name = 'pdf.html'
def get(self, request, *args, **kwargs):
template_response = super().get(self, request, *args, **kwargs)
HTML(string=template_response.rendered_content).write_pdf(
'/path/to/test.pdf',
stylesheets=['/path/to/pdf.css']
)
return template_response
在视图之外的更好的解决方案是使用requests来获取HTML页面,然后创建pdf文件。它更好,因为服务器不必等待创建pdf,可能阻止等待服务器的其他请求:
>>>import requests
>>>resp = requests.get('http://my-url/object_id')
>>>HTML(string=resp.content).write_pdf('/path/to/test.pdf', stylesheets=['/path/to/pdf.css'])
答案 2 :(得分:1)
此功能对我有用。
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
if not pdf.err:
f = open('test2.pdf', 'wb')
myfile = File(f)
myfile.write(result.getvalue())
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None