使用附件生成受保护的Django网页的PDF

时间:2017-08-25 15:21:06

标签: python django python-3.x pdf reportlab

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

我已经阅读了大部分关于如何使用pdfkitreportlab从网页生成PDF的帖子,但由于某种原因,所有这些帖子都因我而失败。

目前,我最接近的是使用pdfkit成功生成页面的PDF,但这要求我删除要求用户登录并具有页面权限的限制,这实际上并非如此这是一个长期的选择。我发现了一些帖子,讨论在受保护的页面上打印pdf并提供登录信息,但我无法使用任何这些。

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

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

3 个答案:

答案 0 :(得分:1)

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

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

  1. app/auth_backends.py
  2. 中创建身份验证后端
  3. app.auth_backends.SpoofAuthBackend后端添加到settings.py后面shared_secretuser_id
  4. 创建类似url(r'^spoof-user/(?P<user_id>\d+)/$', 'app.views.spoof_user', name="spoof-user")
  5. 的网址路线
  6. 添加必须同时调用spoof_user的视图django.contrib.auth.authenticate(在上面的#1中调用后端),并且在从authenticate(...)获取用户后,您使用用户{{1}填充请求}。最后,如果共享密码错误或django.contrib.auth.login(request, user)您真正想要的PDF网址(通过HttpResponseForbiddenHttpResponseRedirect以编程方式登录欺骗用户后,此视图应返回authenticate )。
  7. 您可能希望使用类似login的内容为每个请求创建一个随机密钥,这些密钥会持续共享密钥30秒以留出请求时间。然后执行cache.set('spoof-user-%s' % user_id, RANDOM_STRING, 30)。您的新视图将测试身份验证后端中提供的pdf_response = requests.get("%s?shared_secret=1a2b3c&redirect_uri=/path/to/pdf/" % reverse('spoof-user', kwargs={'user_id': 1234})),登录用户请求并执行重定向到shared_secret

答案 1 :(得分:1)

我搞定了!通过PyPDF2和pdfkit的组合,我的工作非常简单。它适用于受保护的页面,因为django负责将完整的html作为字符串,我只是传递给pdfkit。它还支持附加附件,但我怀疑(虽然我没有测试过)它适用于除pdfs之外的任何东西。

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"))

答案 2 :(得分:-1)

您可以使用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')
`