You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

  1. 创建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>
  1. 视图中渲染并转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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 09:41:29