使用django-wkhtmltopdf生成PDF时将其保存到磁盘

问题描述

我要实现的是这样:

  1. 用户查询参数从React FE微服务发送到Django BE微服务。
    • URI类似于/api/reports?startingPage=12&dataView=Region
    • 这些PDF太大了,无法在FE中生成,因此请在服务器端进行
  2. 请求进入view.py,在其中从数据库查询dataView=Region相关的数据,遍历每一行,并为每个项目生成PDF报告
    • 每个dataView=Region可以包含几百个项目,并且每个项目都是其自己的报告,可以是一页或几页长
  3. 生成报告后,应将其保存到服务器的持久卷声明中,并且 应发送回FE,直到它们全部运行为止。
  4. 当它们全部运行后,我计划使用PyPDF2将所有PDF合并为一个文件
  5. 这时,文件被发送回FE进行下载。

目前我仅在1.和3.上工作,我无法:

  1. 获取文件以保存到存储空间
  2. 防止在PDF生成后将其发送回FE的认行为

正在生成PDF,所以很好。

我正在尝试实施此处找到的建议,但没有得到预期的结果:

Save pdf from django-wkhtmltopdf to server (instead of returning as a response)

这是我目前在Django方面所拥有的:

# urls.py

from django.urls import path

from .views import GeneratePDFView

app_name = 'Reports'

urlpatterns = [
    path('/api/reports',GeneratePDFView.as_view(),name='generate_pdf'),]

# views.py

from django.conf import settings
from django.views.generic.base import TemplateView

from rest_framework.permissions import IsAuthenticated

from wkhtmltopdf.views import PDFTemplateResponse

# Create your views here.

class GeneratePDFView(TemplateView):
    permission_classes = [IsAuthenticated]
    template_name = 'test.html'
    filename = 'test.pdf'

    def generate_pdf(self,request,**kwargs):
        context = {'key': 'value'}

        # generate response
        response = PDFTemplateResponse(
            request=self.request,template=self.template_name,filename=self.filename,context=context,cmd_options={'load-error-handling': 'ignore'})

        self.save_pdf(response.rendered_content,self.filename)

    # Handle saving the document
    # This is what I'm using elsewhere where files are saved and it works there
    def save_pdf(self,file,filename):
        with open(settings.PDF_DIR + '/' + filename,'wb+') as destination:
            for chunk in file.chunks():
                destination.write(chunk)
# settings.py
...
DOWNLOAD_ROOT = '/mnt/files/client-downloads/'
MEDIA_ROOT = '/mnt/files/client-submissions/'
PDF_DIR = '/mnt/files/pdf-sections/'
...

我应该注意其他DOWNLOAD_ROOTMEDIA_ROOT在应用程序使用它们的地方工作正常。我什至尝试使用settings.MEDIA_ROOT,因为我知道它可以工作,但仍然没有任何保存。但是如您所见,我是从超级基础开始的,还没有添加查询,循环等。

我的save_pdf()与我链接的SO问题不同,因为这是我在应用程序其他部分中使用的内容,并且可以在其中保存文件。我确实尝试了他们在SO问题中提供的内容,但是却得到了相同的结果,但并没有保存。就是这样:

with open("file.pdf","wb") as f:
    f.write(response.rendered_content)

那我要怎么做才能将这些PDF保存到磁盘?

也许我需要使用其他库来满足自己的需要,因为django-wkhtmltopdf似乎开箱即用,我不希望我不清楚自己是否可以覆盖。 >

解决方法

好吧,我的大脑顺畅地通宵达旦,今天早上弄清楚了:

# views.py

class GeneratePDFView(TemplateView):
    permission_classes = [IsAuthenticated]

    def get(self,request,*args,**kwargs):
        template_name = 'test.html'
        filename = 'test.pdf'
        context = {'key': 'value'}

        # generate response
        response = PDFTemplateResponse(
            request=request,template=template_name,filename=filename,context=context,cmd_options={'load-error-handling': 'ignore'})

        # write the rendered content to a file
        with open(settings.PDF_DIR + '/' + filename,"wb") as f:
            f.write(response.rendered_content)

        return HttpResponse('Hello,World!')

这将PDF保存到磁盘,并且也没有响应PDF。显然,这是我可以扩展的功能最少的示例,但至少可以弄清楚这两个问题。