生成带有附件的受保护 Django 网页的 PDF



所以我正在尝试生成我在 django Web 应用程序中拥有的视图的 PDF。 此视图受保护,这意味着用户必须登录并具有查看页面的特定权限。 我还有一些附件(作为FileFields存储在数据库中(,我想将其附加到PDF的末尾。

我已经阅读了我能找到的大多数关于如何使用pdfkitreportlab从网页生成 PDF 的文章,但由于某种原因,所有这些帖子对我来说都失败了。

目前,我得到的最接近的是使用pdfkit成功生成页面的 PDF,但这需要我删除要求用户登录并拥有页面权限的限制,这真的不是一个长期的选择。 我发现了几篇讨论在受保护页面上打印pdf并提供登录信息的帖子,但我无法获得任何工作。

我还没有找到任何关于如何包含附件的信息,也不知道从哪里开始。

如果需要,我非常乐意用更多信息或代码片段更新这个问题,但这里有很多活动部分,我不想用无用的信息淹没人们。 如果还有其他信息,请告诉我我应该提供的任何其他信息,并提前感谢任何帮助。

我让它工作了! 通过 PyPDF2 和 pdfkit 的组合,我让这个工作非常简单。 它适用于受保护的页面,因为 django 负责将完整的 html 作为字符串获取,我只是将其传递给 pdfkit。 它还支持附加附件,但我怀疑(尽管我还没有测试过(它是否适用于 pdf 以外的任何东西。

from django.template.loader import get_template
from PyPDF2 import PdfFileWriter, PdfFileReader
import pdfkit
def append_pdf(pdf, output):
[output.addPage(pdf.getPage(page_num)) for page_num in range(pdf.numPages)]

def render_to_pdf():
t = get_template('app/template.html')
c = {'context_data': context_data}
html = t.render(c)
pdfkit.from_string(html, 'path/to/file.pdf')
output = PdfFileWriter()
append_pdf(PdfFileReader(open('path/to/file.pdf', "rb")), output)
attaches = Attachment.objects.all()
for attach in attaches:
append_pdf(PdfFileReader(open(attach.file.path, "rb")), output)
output.write(open('path/to/file_with_attachments.pdf', "wb"))

如果您只想保护它,则可以编写一个自定义身份验证后端,让您的服务器欺骗用户。矫枉过正,但它可以解决您的问题,至少您可以了解自定义身份验证后端!(注意:您应该使用 HTTPS。

https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#writing-an-authentication-backend

  1. app/auth_backends.py中创建身份验证后端
  2. app.auth_backends.SpoofAuthBackend后端添加到需要shared_secretuser_idsettings.py
  3. 创建类似url(r'^spoof-user/(?P<user_id>d+)/$', 'app.views.spoof_user', name="spoof-user")的 URL 路由
  4. 添加必须调用两个django.contrib.auth.authenticate的视图spoof_user(在上面的 #1 中调用后端(,并在从authenticate(...)获取用户后使用用户django.contrib.auth.login(request, user)填充请求。最后,如果共享密钥错误或HttpResponseRedirect到您实际想要的 PDF URL(通过authenticatelogin以编程方式登录欺骗用户后(,此视图应返回HttpResponseForbidden

您可能希望使用类似cache.set('spoof-user-%s' % user_id, RANDOM_STRING, 30)的东西为每个请求创建一个随机密钥,该密钥将共享密钥保留 30 秒以留出请求时间。然后执行pdf_response = requests.get("%s?shared_secret=1a2b3c&redirect_uri=/path/to/pdf/" % reverse('spoof-user', kwargs={'user_id': 1234}))。您的新视图将在身份验证后端测试提供的shared_secret,登录用户以请求并执行重定向到request.GET.get('redirect_uri')

你可以使用 pdfkit 来做到这一点。您可以使用 url 检索页面,pdfkit 将处理其余的工作:

pdfkit.from_url('http://website.com/somepage', 'somepage.pdf')

您必须使用适当的标题正确访问该页面,因为它当然受到保护:

options = {
'cookie': [
('cookie-name1', 'cookie-value1'),
('cookie-name2', 'cookie-value2'),
]
}
pdfkit.from_url('http://website.com/somepage', 'somepage.pdf')
`

最新更新