在 Django Views For 循环中生成多个 PDF 报告

Generate multiple PDF report in Django Views For loop

在我的Django应用中,在一个Batch中,有多个Inquiries。每个 Inquiry 都有一个相关的 Candidate。候选人有多个地址。我想生成一个包含所有候选人及其相关地址的 PDF。我正在使用 Wea​​syprint 生成 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 并退出函数。