Django表单提交后生成含用户输入数据的PDF解决方案求助
Django表单提交后生成带用户数据的PDF解决方案
一、先确认表单数据已正确获取
不管使用Django的Form类还是直接处理POST请求,第一步要确保视图中拿到了用户提交的有效数据:
用Django Form类的示例
from django import forms from django.shortcuts import render from django.http import HttpResponse from io import BytesIO class UserInfoForm(forms.Form): name = forms.CharField(label='姓名') age = forms.IntegerField(label='年龄') is_student = forms.BooleanField(label='是否学生', required=False) gender = forms.ChoiceField(label='性别', choices=[('M', '男'), ('F', '女')]) birthday = forms.DateField(label='生日', widget=forms.DateInput(attrs={'type': 'date'})) def form_submit(request): if request.method == 'POST': form = UserInfoForm(request.POST) if form.is_valid(): # 获取清洗后的结构化数据 form_data = form.cleaned_data # 调用PDF生成函数 pdf_buffer = generate_pdf(form_data) # 返回下载响应 response = HttpResponse(pdf_buffer, content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename="user_info.pdf"' return response else: form = UserInfoForm() return render(request, 'form.html', {'form': form})
直接处理POST参数的示例(无Form类)
import datetime def form_submit(request): if request.method == 'POST': form_data = { 'name': request.POST.get('name'), 'age': int(request.POST.get('age', 0)), 'is_student': request.POST.get('is_student') == 'on', 'gender': request.POST.get('gender'), 'birthday': datetime.datetime.strptime(request.POST.get('birthday'), '%Y-%m-%d').date() } # 后续PDF生成逻辑同上
二、两种填充数据生成PDF的实现方式
方式1:用ReportLab直接绘制(适合简单布局)
先安装依赖:pip install reportlab
from reportlab.pdfgen import canvas from reportlab.lib.pagesizes import letter def generate_pdf(form_data): buffer = BytesIO() # 初始化PDF画布 p = canvas.Canvas(buffer, pagesize=letter) page_width, page_height = letter # 绘制标题与数据 y_pos = page_height - 100 p.drawString(100, y_pos, "用户信息表单") y_pos -= 40 p.drawString(100, y_pos, f"姓名: {form_data['name']}") y_pos -= 20 p.drawString(100, y_pos, f"年龄: {form_data['age']}") y_pos -= 20 p.drawString(100, y_pos, f"是否学生: {'是' if form_data['is_student'] else '否'}") y_pos -= 20 p.drawString(100, y_pos, f"性别: {'男' if form_data['gender'] == 'M' else '女'}") y_pos -= 20 p.drawString(100, y_pos, f"生日: {form_data['birthday'].strftime('%Y-%m-%d')}") # 完成绘制并保存 p.showPage() p.save() buffer.seek(0) return buffer
空PDF排查点:检查form_data是否有值,确认drawString等绘制方法被调用,且没有遗漏showPage()和save()。
方式2:HTML模板渲染转PDF(适合复杂样式)
用Django模板渲染带数据的HTML,再通过WeasyPrint转PDF,更易维护复杂布局。
先安装依赖:pip install weasyprint
- 创建HTML模板(
templates/pdf_template.html):
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> .container { width: 80%; margin: 2rem auto; } .field-row { margin: 1rem 0; display: flex; gap: 1rem; } .label { width: 120px; font-weight: bold; } </style> </head> <body> <div class="container"> <h1>用户信息表单</h1> <div class="field-row"> <span class="label">姓名:</span> <span>{{ name }}</span> </div> <div class="field-row"> <span class="label">年龄:</span> <span>{{ age }}</span> </div> <div class="field-row"> <span class="label">是否学生:</span> <span>{{ '是' if is_student else '否' }}</span> </div> <div class="field-row"> <span class="label">性别:</span> <span>{{ '男' if gender == 'M' else '女' }}</span> </div> <div class="field-row"> <span class="label">生日:</span> <span>{{ birthday|date:"Y-m-d" }}</span> </div> </div> </body> </html>
- 视图中渲染并转PDF:
from django.template.loader import render_to_string from weasyprint import HTML def generate_pdf(form_data): # 渲染模板,传入表单数据 html_content = render_to_string('pdf_template.html', form_data) # HTML转PDF buffer = BytesIO() HTML(string=html_content).write_pdf(buffer) buffer.seek(0) return buffer
空PDF排查点:打印html_content确认是否渲染出带数据的内容,检查模板变量名与form_data的键是否完全匹配。
三、通用排查要点
- 打印
form_data确认用户提交的数据已被正确获取,没有为空的情况。 - 检查PDF生成逻辑:ReportLab需确保调用
showPage()和save();WeasyPrint需确保HTML内容不为空。 - 确认响应头设置正确:
content_type为application/pdf,Content-Disposition正确指定下载文件名。
内容的提问来源于stack exchange,提问作者user20302684
相关产品推荐
相关产品推荐

