Generate PDF of Protected Django Webpage with Attachments

别来无恙 提交于 2019-12-02 11:34:39

问题


So I'm trying to generate a PDF of a view that I have in a django web application. This view is protected, meaning the user has to be logged in and have specific permission to view the page. I also have some attachments (stored in the database as FileFields) that I would like to append to the end of the PDF.

I've read most of the posts I could find on how to generate PDFs from a webpage using pdfkit or reportlab, but all of them fail for me for some reason or another.

Currently, the closest I've gotten is successfully generating a PDF of the page using pdfkit, but this requires me to remove the restrictions that require the user to be logged in and have page permissions, which really isn't an option long term. I found a couple posts that discuss printing pdfs on protected pages and providing login information, but I couldn't get any of that to work.

I haven't found anything on how to include attachments, and don't really know where to start with that.

I'm more than happy to update this question with more information or snippets of code if need be, but there's quite a few moving parts here and I don't want to flood people with useless information. Let me know if there's any other information I should provide, and thanks in advance for any help.


回答1:


If you just want to secure it, you could write a custom Authentication Backend that lets your server spoof users. Way over-kill but it would solve your problem and at least you get to learn about custom auth backends! (Note: You should be using HTTPS.)

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

  1. Create auth backend in app/auth_backends.py
  2. Add app.auth_backends.SpoofAuthBackend backend to settings.py that takes a shared_secret and user_id.
  3. Create a URL route like url(r'^spoof-user/(?P<user_id>\d+)/$', 'app.views.spoof_user', name="spoof-user")
  4. Add the view spoof_user that must invoke both django.contrib.auth.authenticate (which invokes backend in #1 above) and after getting user from authenticate(...) you pad the request with the user django.contrib.auth.login(request, user). Finally, this view should return HttpResponseForbidden if the shared secret is wrong or HttpResponseRedirect to the PDF URL you actually want (after logging in to spoof user programmatically via authenticate and login).

You would probably want to create a random secret key each request using something like cache.set('spoof-user-%s' % user_id, RANDOM_STRING, 30) which persists shared secret for 30 seconds to allow time for request. Then perform pdf_response = requests.get("%s?shared_secret=1a2b3c&redirect_uri=/path/to/pdf/" % reverse('spoof-user', kwargs={'user_id': 1234})). Your new view will test the provided shared_secret in auth backend, login user to request and perform redirect to request.GET.get('redirect_uri').




回答2:


I got it working! Through a combination of PyPDF2 and pdfkit, I got this to work pretty simply. It works on protected pages because django takes care of getting the complete html as a string, which I just pass to pdfkit. It also supports appending attachments, but I doubt (though I haven't tested) that it works with anything other than 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"))



回答3:


You can use pdfkit to do that. You can retrieve the page using the url and pdfkit will handle the rest:

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

You will have to properly access the page using the appropriate headers for it is protected of course:

options = {
    'cookie': [
        ('cookie-name1', 'cookie-value1'),
        ('cookie-name2', 'cookie-value2'),
    ]
}

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


来源:https://stackoverflow.com/questions/45884654/generate-pdf-of-protected-django-webpage-with-attachments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!