为什么在 django 中使用 xhtml2pdf 呈现为 pdf 时 html table 中的某些列会折叠?
Why some of the column in html table collapsing when rendered to pdf using xhtml2pdf in django?
我正在尝试使用 xhtml2pf 在 Django 中生成 pdf。 HTML 模板主要由 HTML table 组成。呈现 pdf 时,Django PhoneField 和 EmailField 会折叠。
下面是在context中传递Django PhoneField和EmailField时生成的pdf图片-
html模板的上下文如下-
user_dict = {
"full_name": user.full_name,
"email": str(user.email),
"phone_number": str(user.phone_number),
"emergency_number": "very very long header",
"id_proof_number": user.id_proof_number
}
当我使用纯字符串代替 django 字段时,它正确呈现如下 -
使用的上下文如下-
user_dict = {
"full_name": user.full_name,
"email": "joe@gmail.com",
"phone_number": "+14151234567",
"emergency_number": "very very long header",
"id_proof_number": user.id_proof_number
}
Django 模型-
class User(models.Model):
trip = models.ForeignKey(
Trip, on_delete=models.CASCADE, related_name="users")
id_proof_number = models.CharField(
_("Id Proof"), max_length=100, null=True, blank=True)
full_name = models.CharField(_("Full name"), max_length=255)
email = models.EmailField(_("email"), max_length=70)
phone_number = PhoneNumberField(_("Phone Number"))
emergency_number = PhoneNumberField(_("Emergency Number"), default=None, null=True)
HTML 模板-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>User Details</title>
<style type="text/css">
@page {
size: A4;
margin: 1cm;
}
.card-header{
text-align: center;
}
.table{
border: 0.5px solid #ababab;
text-align: center;
width: 100%;
max-width: 100%;
margin-bottom: 5px;
table-layout:fixed;
}
.table tr th td{
white-space: nowrap;
}
.table th {
padding: 5px;
vertical-align: top;
background-color: #e8e8e8;
}
.table td {
padding: 5px;
vertical-align: top;
-pdf-keep-with-next: false;
}
.five {
width: 5%;
}
.twenty {
width: 20%;
}
.fifteen {
width: 15%;
}
</style>
</head>
<body>
<div class="container">
<div class="card">
<div class="card-header">
<h3>Header</h3>
</div>
</div>
<table class = "table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Phone number</th>
<th>Email</th>
<th>ID</th>
<th>emergency number</th>
</tr>
</thead>
<tbody>
{% for trip in trips %}
{% for member in trip.users %}
<tr>
{% if forloop.counter == 1 %}
<td rowspan="{{trip.users|length}}">{{trip.id}}</td>
{% endif %}
<td>{{member.full_name}}</td>
<td>{{member.phone_number}}</td>
<td>{{member.email}}</td>
<td>{{member.id_proof_number}}</td>
<td>very very long header</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
用于呈现 pdf 的 Django 视图-
def trip_members_pdf(request, id):
trip_qs = Trip.objects.filter(parent_id=id)
trips = []
for trip in trip_qs:
trip_dict = {
"id": trip.id,
"users": []
}
users = trip.users.all()
for user in users:
user_dict = {
"full_name": user.full_name,
"email": "joe@gmail.com",
"phone_number": "+14151234567",
"emergency_number": user.emergency_number,
"id_proof_number": user.id_proof_number
}
trip_dict["users"].append(user_dict)
trips.append(trip_dict)
return PDFRender.render('docs/trip_member_pdf.html', { 'tour': tour, 'trips': trips})
PDF 渲染器-
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
import xhtml2pdf.pisa as pisa
class PDFRender:
@staticmethod
def render(path: str, params: dict = {}):
template = get_template(path)
html = template.render(params)
response = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), response)
if not pdf.err:
return HttpResponse(response.getvalue(), content_type='application/pdf')
else:
return HttpResponse("Error Rendering PDF", status=400)
我找到了这种行为的原因。如果列中的任何值是 None,则渲染器正在折叠该列。我在 None 的情况下传递了空白 space 并且一切正常。我改变了上下文如下-
user_dict = {
"full_name": user.full_name,
"email": user.email or " ",
"phone_number": user.phone_number or " ",
"emergency_number": "very very long header",
"id_proof_number": user.id_proof_number
}
我正在尝试使用 xhtml2pf 在 Django 中生成 pdf。 HTML 模板主要由 HTML table 组成。呈现 pdf 时,Django PhoneField 和 EmailField 会折叠。
下面是在context中传递Django PhoneField和EmailField时生成的pdf图片-
html模板的上下文如下-
user_dict = {
"full_name": user.full_name,
"email": str(user.email),
"phone_number": str(user.phone_number),
"emergency_number": "very very long header",
"id_proof_number": user.id_proof_number
}
当我使用纯字符串代替 django 字段时,它正确呈现如下 -
使用的上下文如下-
user_dict = {
"full_name": user.full_name,
"email": "joe@gmail.com",
"phone_number": "+14151234567",
"emergency_number": "very very long header",
"id_proof_number": user.id_proof_number
}
Django 模型-
class User(models.Model):
trip = models.ForeignKey(
Trip, on_delete=models.CASCADE, related_name="users")
id_proof_number = models.CharField(
_("Id Proof"), max_length=100, null=True, blank=True)
full_name = models.CharField(_("Full name"), max_length=255)
email = models.EmailField(_("email"), max_length=70)
phone_number = PhoneNumberField(_("Phone Number"))
emergency_number = PhoneNumberField(_("Emergency Number"), default=None, null=True)
HTML 模板-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>User Details</title>
<style type="text/css">
@page {
size: A4;
margin: 1cm;
}
.card-header{
text-align: center;
}
.table{
border: 0.5px solid #ababab;
text-align: center;
width: 100%;
max-width: 100%;
margin-bottom: 5px;
table-layout:fixed;
}
.table tr th td{
white-space: nowrap;
}
.table th {
padding: 5px;
vertical-align: top;
background-color: #e8e8e8;
}
.table td {
padding: 5px;
vertical-align: top;
-pdf-keep-with-next: false;
}
.five {
width: 5%;
}
.twenty {
width: 20%;
}
.fifteen {
width: 15%;
}
</style>
</head>
<body>
<div class="container">
<div class="card">
<div class="card-header">
<h3>Header</h3>
</div>
</div>
<table class = "table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Phone number</th>
<th>Email</th>
<th>ID</th>
<th>emergency number</th>
</tr>
</thead>
<tbody>
{% for trip in trips %}
{% for member in trip.users %}
<tr>
{% if forloop.counter == 1 %}
<td rowspan="{{trip.users|length}}">{{trip.id}}</td>
{% endif %}
<td>{{member.full_name}}</td>
<td>{{member.phone_number}}</td>
<td>{{member.email}}</td>
<td>{{member.id_proof_number}}</td>
<td>very very long header</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
用于呈现 pdf 的 Django 视图-
def trip_members_pdf(request, id):
trip_qs = Trip.objects.filter(parent_id=id)
trips = []
for trip in trip_qs:
trip_dict = {
"id": trip.id,
"users": []
}
users = trip.users.all()
for user in users:
user_dict = {
"full_name": user.full_name,
"email": "joe@gmail.com",
"phone_number": "+14151234567",
"emergency_number": user.emergency_number,
"id_proof_number": user.id_proof_number
}
trip_dict["users"].append(user_dict)
trips.append(trip_dict)
return PDFRender.render('docs/trip_member_pdf.html', { 'tour': tour, 'trips': trips})
PDF 渲染器-
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
import xhtml2pdf.pisa as pisa
class PDFRender:
@staticmethod
def render(path: str, params: dict = {}):
template = get_template(path)
html = template.render(params)
response = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), response)
if not pdf.err:
return HttpResponse(response.getvalue(), content_type='application/pdf')
else:
return HttpResponse("Error Rendering PDF", status=400)
我找到了这种行为的原因。如果列中的任何值是 None,则渲染器正在折叠该列。我在 None 的情况下传递了空白 space 并且一切正常。我改变了上下文如下-
user_dict = {
"full_name": user.full_name,
"email": user.email or " ",
"phone_number": user.phone_number or " ",
"emergency_number": "very very long header",
"id_proof_number": user.id_proof_number
}