Django is Python。在我们前一篇教程里,我们用Django + PyPDF2开发了个小Web应用,实现了PDF页面提取。在今天这个项目里,我们将实现2个PDF文件的合并。如果你要练习这个项目,你首先要确保已安装Django 2.X + Python 3.X。如果你还没有安装PyPDF2,可以通过pip install PyPDF2安装好这个第三方Python包。如果你喜欢我们的原创文章,欢迎关注我们的微信公众号【Python与Django大咖之路】。
项目开发总体思路
我们的开发思路是这样子的。我们设计一个表单,让用户按顺序上传2个PDF文件。服务器在收到PDF文件后使用PyPDF2读取用户上传的PDF文件,在后台完成合并,然后通过Django的HttpResponse方法将这个新生成的PDF文件通过浏览器返回给客户。
因为这个应用很简单。我们在之前项目基础上,只需要增加一个功能性页面,并在views.py里增加了一个pdf_merge方法。整个项目不需要建Models模型。
第一步 创建项目,设计URL
在CMD终端里输入python manage.py startapp pdf创建一个叫pdf的app,然后把这个app加入到你的myproject/settings.py里INSTALLED_APPS去。
#myproject/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'pdf',
]
在pdf文件目录下创建一个urls.py, 添加如下代码。更多URL编写知识见Django核心技术基础(2): URL的设计与配置。
fromdjango.urlsimportpath,re_path
from.importviews
# namespace
app_name ='pdf'
urlpatterns = [
# 上传pdf,用户输入需要提取的页面, 返回需要提取的页面
path('extract/',views.pdf_extract,name='pdf_extract'),
path('merge/',views.pdf_merge,name='pdf_merge'),
]
同时我们应将上述urls加入到myproject/urls.py里去。这样当用户通过浏览器访问/pdf/merge/时,服务器就会调用我们views里的pdf_merge方法来处理用户的请求。
fromdjango.contribimportadmin
fromdjango.urlsimportpath,include
# 对于处理静态文件如图片,CSS和文本非常重要
fromdjango.confimportsettings
fromdjango.conf.urls.staticimportstatic
urlpatterns = [
path('admin/',admin.site.urls),
path('pdf/',include('pdf.urls')),
] + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
第二步 设计表单forms.py
因为我们在视图view里需要使用到上传文件的表单,所以我们这里先设计表单PdfMergeForm。这个表单非常简单,只有2个字段file1和file2。如下所示。
# pdf/models.py
fromdjangoimportforms
classPdfMergeForm(forms.Form):
file1 = forms.FileField(label="上传PDF文件1")
file2 = forms.FileField(label="上传PDF文件2")
第三步 编写视图views.py
视图view是本项目中最重要的部分。其总体思路,我已经在代码中加了很多注释帮你理解。PyPDF2功能强大,几乎完成所有常见的PDF文件操作,比如读写,合并,添加书签等, 比Django文档里提到的reportlab要好很多。今天我们主要用PyPDF2的PdfFileReader方法读取PDF文件,利用PdfFileMerger实现文件的合并,最后通过Django输出给用户。
fromdjango.shortcutsimportrender
fromdjango.httpimportHttpResponse
from.formsimportPdfExtractForm,PdfMergeForm
importPyPDF2
# Create your views here.
defpdf_merge(request):
ifrequest.method =='POST':
# 如果用户通过POST提交
form = PdfMergeForm(request.POST,request.FILES)
ifform.is_valid():
# 获取上传的文件1
f1 = request.FILES['file1']
# 获取上传的文件2
f2 = request.FILES['file2']
# 转化为PDF文件对象
pdfFileObj1 = PyPDF2.PdfFileReader(f1)
pdfFileObj2 = PyPDF2.PdfFileReader(f2)
# 创建PDF文件合并对象,添加合并文件
pdfMerger = PyPDF2.PdfFileMerger()
pdfMerger.append(pdfFileObj1)
pdfMerger.append(pdfFileObj2)
# 将合并文件对象写入到merged_file.pdf
withopen('merged_file.pdf','wb')aspdfOutputFile:
pdfMerger.write(pdfOutputFile)
# 打开合并的merged_file.pdf,通过HttpResponse输出
withopen('merged_file.pdf','rb')asmerged_file:
response = HttpResponse(merged_file.read(),content_type='application/pdf')
response['Content-Disposition'] ='attachment; filename="merged_file.pdf"'
returnresponse
else:
# 如果通过POST提交,但表单未通过验证
form = PdfMergeForm()
else:
# 如果用户没有通过POST,提交生成空表单
form = PdfMergeForm()
returnrender(request,'pdf/pdf_merge.html',{'form': form})
上述代码中最值得需要你注意的地方是我们如何通过HttpReponse将生成的pdf文档返回给用户的。下行代码是最重要的,它不仅读取了打开的pdf文件的内容,还指定了返回内容类型是pdf文件, 否则会出现乱码。
response = HttpResponse(pdfExtract.read(), content_type='application/pdf')
第四步 编写模板template
模板文件非常简单,如下所示。我们在pdf文件夹里创建了一个templates文件夹,又在里面创建了一个新的pdf文件夹,然后把模板文件放里面了。至于为什么我们这么布局,请阅读Django项目推荐性的文件与文件夹布局。
# pdf/templates/pdf/pdf_merge.html
{% block content %}
PDF文件合并
{% csrf_token %}
{{ form.as_p }}
PDF页面提取|PDF文件合并
{% endblock %}
第五步 查看效果
现在你在CMD终端里输入python manage.py runserver。在浏览器中打开http://127.0.0.1:8000/pdf/merge/你就可以看到如下效果了。
点击确定,会自动返回2个合并好了的PDF文件。
你知道这个APP最大的特点是什么吗?用户上传的文件根本不会存储下来,这样你就不用担心用户上传文件数量过多而硬盘空间不够大啦。
第六步 想想需要改进的地方
整个项目离实际应用还有许多需要改进的地方,比如:
如果用户上传的不是PDF文件怎么处理?
用户上传的PDF文件过大怎么办?
这些问题就留给读者你思考吧。后续我们会不断完善这个PDF文件操作APP,比如实现文件格式互转,PDF文件添加书签。欢迎关注我们的微信公众号。如果有问题,也欢迎给我们留言。
领取专属 10元无门槛券
私享最新 技术干货