2017-08-25 95 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