2017-08-25 97 views
1

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

我读过的大部分帖子都是关于如何使用pdfkitreportlab从网页生成PDF文件的,但所有这些文章都因为某种原因而失败。

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

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

如果需要更多信息或代码片段,我很乐意更新这个问题,但是这里有很多移动部件,我不想用无用的信息淹没人们。让我知道是否有其他信息我应该提供,并提前感谢任何帮助。

回答

1

我明白了!通过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")) 
-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') 
` 
+0

我有点困惑。选项对象的结构看起来像是为了让应用程序能够正确登录?正如我在我的问题中提到的那样,我曾尝试过类似的方式,但无法实现。我正在使用内置的django用户验证。另外,你不需要将该选项对象以某种方式传递给pdfkit吗?而且我仍然需要能够添加附件。 – Nealon

1

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

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

  1. 创建auth后端在app/auth_backends.py
  2. 添加app.auth_backends.SpoofAuthBackend后端settings.py,需要一个shared_secretuser_id
  3. 创建像url(r'^spoof-user/(?P<user_id>\d+)/$', 'app.views.spoof_user', name="spoof-user")
  4. 一个URL路径添加必须调用视图spoof_user二者django.contrib.auth.authenticate(它调用在上述#1的后端),并从authenticate(...)获取用户你垫与所述用户django.contrib.auth.login(request, user)请求之后。最后,如果共享密钥错误,则该视图应该返回HttpResponseForbidden,或者HttpResponseRedirect返回到您实际需要的PDF URL(在通过authenticatelogin以编程方式登录以欺骗用户之后)。

您可能想要使用类似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}))。您的新视图将在auth后端测试提供的shared_secret,登录用户请求并执行重定向至request.GET.get('redirect_uri')

+0

我还会补充一点,我使用'wkhtmltopdf'完全在服务器端生成所有PDF文件,但能够欺骗用户可能对某些项目很有用。例如,仅供管理员或帮助台人员能够登录和查看他们的项目以帮助解决支持问题等。 – pztrick

+1

我还刚刚上传了显示'django-wkhtmltopdf'用法的要点:https://gist.github。 com/pztrick/94a90908954bcdb5f672f00aa4d9b2de请注意,您需要重构视图,以便将相同的'context'字典传递给模板,而不是像request.user'那样访问。 – pztrick

+0

这个要点看起来更合理,和我正在研究的东西类似......我会用这个来测试。任何想法如何我可以附件附件? – Nealon