在 Django Views For 循环中生成多个 PDF 报告
Generate multiple PDF report in Django Views For loop
在我的Django应用中,在一个Batch中,有多个Inquiries。每个 Inquiry 都有一个相关的 Candidate。候选人有多个地址。我想生成一个包含所有候选人及其相关地址的 PDF。我正在使用 Weasyprint 生成 PDF。
Models.py
class Batch(models.Model):
batch = models.CharField(verbose_name='Reference Number', max_length=200)
class Candidate(models.Model):
name = models.CharField(help_text='', max_length=200)
nationality = models.CharField(max_length=200)
class Address(models.Model):
DEFAULT_COUNTRY_ID = 1
PERA= 'Permanant Address'
PREA= 'Present Address'
ADDRESS_TYPE_CHOICES = [
(PERA, 'Permanant Address'),
(PREA, 'Present Address'),
]
candidate = models.ForeignKey(Candidate, on_delete=models.CASCADE, verbose_name='Candidate')
nid = models.CharField(verbose_name='NID', max_length = 15, unique = True, null=True, blank=False)
address_type = models.CharField(max_length=200, choices=ADDRESS_TYPE_CHOICES)
address_line_1 = models.CharField('Address Line 1', max_length=1000, null=True, blank=True)
state = models.ForeignKey(State, on_delete=models.CASCADE,)
city = models.ForeignKey(City, on_delete=models.CASCADE,)
country = models.ForeignKey(Country, on_delete=models.CASCADE, default=DEFAULT_COUNTRY_ID)
class Inquiry(models.Model):
batch = models.ForeignKey(Batch, on_delete=models.CASCADE, null=True,)
candidate = models.ForeignKey(Candidate, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(verbose_name='Name', help_text='', max_length=200)
nid = models.CharField(verbose_name='NID', max_length = 15, null=True, blank=False)
这是我试过的。但它只是生成第一个 Candidate 的多个实例。我如何生成包含所有候选人及其相关地址的 PDF?
views.py
def download_batch_report(request, pk):
inquiries = Inquiry.objects.filter(batch=pk)
batch = get_object_or_404(Batch, id=pk)
for inquiry in inquiries:
inquiry = get_object_or_404(Inquiry, id=inquiry.id)
candidate = get_object_or_404(Candidate, nid=inquiry.nid)
addresses = Address.objects.filter(candidate=candidate)
print_time = timezone.now()
font_config = FontConfiguration()
context = {'batch': batch, 'inquiries': inquiries, 'inquiry': inquiry, 'candidate': candidate,'addresses': addresses, 'print_time': print_time}
html_string = render_to_string('ssvr/batch/report.html', context).encode(encoding="UTF-8")
css = CSS(string='''
@font-face {
font-family: kalpurush;
src: url(file:///mnt/d/djangoprojects/dj-boot-modal/librarydb/static/librarydb/fonts/kalpurush.ttf);
}''', font_config=font_config)
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'inline; filename='+str(batch.batch)+'_'+str(timezone.now())+'.pdf'
HTML(string=html_string).write_pdf(response, stylesheets=[css], presentational_hints=True, font_config=font_config)
return response
report.html
<!DOCTYPE html>
<html lang="en">
{% load static %}
{% load tz %}
<head>
<meta charset="UTF-16">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{ batch.batch }}</title>
</head>
<body>
{% for inquiry in inquiries %}
<div id="content" class="border_sx">
<div class="profile">
<div class="row">
1. Full Name: {{ candidate.name }} <br>
2. Nationality: {{ candidate.nationality }} <br>
<hr>
</div>
<div class="row">
{% for address in addresses %}
{% if address.address_type == 'Permanant Address' %}
3. Permanant Address: {{ address.address_line_1 }}, {{ address.city }}, {{ address.state }}, {{ address.country }}
{% endif %}
{% endfor %} <br>
{% for address in addresses %}
{% if address.address_type == 'Present Address' %}
4. Present Address: {{ address.address_line_1 }}, {{ address.city }}, {{ address.state }}, {{ address.country }}
{% endif %}
{% endfor %}
</div> <br>
<hr>
<br>
<div>
<div>
<p>
Report Generated at:
{% localtime on %}
{{ print_time|timezone:"Asia/Dhaka" }}
{% endlocaltime %}
</p>
</div>
</div>
<div class="break"></div>
{% endfor %}
</body>
</html>
不需要在上下文中传递 Candidate
对象。使用 inquiry.candidate
访问附加到每个查询的候选人。地址也一样。使用 inquiry.candidate.address_set.all
遍历这些。
此外,您的视图中不需要 for 循环,因为您在报告中这样做了。在任何情况下,在循环的第一个 运行 处,代码将到达 return 并退出函数。
在我的Django应用中,在一个Batch中,有多个Inquiries。每个 Inquiry 都有一个相关的 Candidate。候选人有多个地址。我想生成一个包含所有候选人及其相关地址的 PDF。我正在使用 Weasyprint 生成 PDF。
Models.py
class Batch(models.Model):
batch = models.CharField(verbose_name='Reference Number', max_length=200)
class Candidate(models.Model):
name = models.CharField(help_text='', max_length=200)
nationality = models.CharField(max_length=200)
class Address(models.Model):
DEFAULT_COUNTRY_ID = 1
PERA= 'Permanant Address'
PREA= 'Present Address'
ADDRESS_TYPE_CHOICES = [
(PERA, 'Permanant Address'),
(PREA, 'Present Address'),
]
candidate = models.ForeignKey(Candidate, on_delete=models.CASCADE, verbose_name='Candidate')
nid = models.CharField(verbose_name='NID', max_length = 15, unique = True, null=True, blank=False)
address_type = models.CharField(max_length=200, choices=ADDRESS_TYPE_CHOICES)
address_line_1 = models.CharField('Address Line 1', max_length=1000, null=True, blank=True)
state = models.ForeignKey(State, on_delete=models.CASCADE,)
city = models.ForeignKey(City, on_delete=models.CASCADE,)
country = models.ForeignKey(Country, on_delete=models.CASCADE, default=DEFAULT_COUNTRY_ID)
class Inquiry(models.Model):
batch = models.ForeignKey(Batch, on_delete=models.CASCADE, null=True,)
candidate = models.ForeignKey(Candidate, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(verbose_name='Name', help_text='', max_length=200)
nid = models.CharField(verbose_name='NID', max_length = 15, null=True, blank=False)
这是我试过的。但它只是生成第一个 Candidate 的多个实例。我如何生成包含所有候选人及其相关地址的 PDF?
views.py
def download_batch_report(request, pk):
inquiries = Inquiry.objects.filter(batch=pk)
batch = get_object_or_404(Batch, id=pk)
for inquiry in inquiries:
inquiry = get_object_or_404(Inquiry, id=inquiry.id)
candidate = get_object_or_404(Candidate, nid=inquiry.nid)
addresses = Address.objects.filter(candidate=candidate)
print_time = timezone.now()
font_config = FontConfiguration()
context = {'batch': batch, 'inquiries': inquiries, 'inquiry': inquiry, 'candidate': candidate,'addresses': addresses, 'print_time': print_time}
html_string = render_to_string('ssvr/batch/report.html', context).encode(encoding="UTF-8")
css = CSS(string='''
@font-face {
font-family: kalpurush;
src: url(file:///mnt/d/djangoprojects/dj-boot-modal/librarydb/static/librarydb/fonts/kalpurush.ttf);
}''', font_config=font_config)
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'inline; filename='+str(batch.batch)+'_'+str(timezone.now())+'.pdf'
HTML(string=html_string).write_pdf(response, stylesheets=[css], presentational_hints=True, font_config=font_config)
return response
report.html
<!DOCTYPE html>
<html lang="en">
{% load static %}
{% load tz %}
<head>
<meta charset="UTF-16">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{ batch.batch }}</title>
</head>
<body>
{% for inquiry in inquiries %}
<div id="content" class="border_sx">
<div class="profile">
<div class="row">
1. Full Name: {{ candidate.name }} <br>
2. Nationality: {{ candidate.nationality }} <br>
<hr>
</div>
<div class="row">
{% for address in addresses %}
{% if address.address_type == 'Permanant Address' %}
3. Permanant Address: {{ address.address_line_1 }}, {{ address.city }}, {{ address.state }}, {{ address.country }}
{% endif %}
{% endfor %} <br>
{% for address in addresses %}
{% if address.address_type == 'Present Address' %}
4. Present Address: {{ address.address_line_1 }}, {{ address.city }}, {{ address.state }}, {{ address.country }}
{% endif %}
{% endfor %}
</div> <br>
<hr>
<br>
<div>
<div>
<p>
Report Generated at:
{% localtime on %}
{{ print_time|timezone:"Asia/Dhaka" }}
{% endlocaltime %}
</p>
</div>
</div>
<div class="break"></div>
{% endfor %}
</body>
</html>
不需要在上下文中传递 Candidate
对象。使用 inquiry.candidate
访问附加到每个查询的候选人。地址也一样。使用 inquiry.candidate.address_set.all
遍历这些。
此外,您的视图中不需要 for 循环,因为您在报告中这样做了。在任何情况下,在循环的第一个 运行 处,代码将到达 return 并退出函数。