简体   繁体   English

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

[英]Saving PDFs to disk as they are generated with django-wkhtmltopdf

What I'm trying to implement is this:我想要实现的是:

  1. User sends query parameters from React FE microservice to the Django BE microservice.用户将查询参数从 React FE 微服务发送到 Django BE 微服务。
    • URI is something like /api/reports?startingPage=12&dataView=Region URI 类似于/api/reports?startingPage=12&dataView=Region
    • These PDFs are way too big to be generated in FE, so doing it server side这些 PDF 太大而无法在 FE 中生成,所以在服务器端进行
  2. Request makes its way into the view.py where the data related to dataView=Region is queried from the database, each row is iterated through and a PDF report is generated for each item请求进入view.py ,从数据库中查询与dataView=Region相关的数据,遍历每一行,并为每个项目生成 PDF 报告
    • Each dataView=Region can consist of a few hundred items and each of those items is its own report that can be a page long or several pages long每个dataView=Region可以包含几百个项目,每个项目都是它自己的报告,可以是一页长或几页长
  3. As the reports are generated, they should be saved to the server persistent volume claim and not be sent back to FE until they have all run.生成报告时,应将它们保存到服务器持久卷声明中,并且在它们全部运行之前不要将它们发送回 FE。
  4. When they have all run, I plan to use pypdf2 to combine all of the PDFs into one large file.当它们全部运行后,我计划使用pypdf2将所有 PDF 合并到一个大文件中。
  5. At that point, the file is sent back to the FE to download.此时,文件将被发送回 FE 进行下载。

I'm only working on 1. and 3. at this point and I'm unable to:我现在只在 1. 和 3. 上工作,我无法:

  1. Get the files to save to storage获取要保存到存储中的文件
  2. Prevent the default behavior of the PDF being sent back to the FE after it has been generated防止 PDF 的默认行为在生成后被发送回 FE

The PDFs are being generated, so that is good.正在生成 PDF,这很好。

I'm trying to implement the suggestions as found here, but I'm not getting the desired results:我正在尝试实施此处找到的建议,但没有得到预期的结果:

Save pdf from django-wkhtmltopdf to server (instead of returning as a response) 将 django-wkhtmltopdf 中的 pdf 保存到服务器(而不是作为响应返回)

This is what I currently have on the Django side:这是我目前在 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/'
...

I should note the other DOWNLOAD_ROOT and MEDIA_ROOT are working fine where the app uses them.我应该注意到其他DOWNLOAD_ROOTMEDIA_ROOT在应用程序使用它们的地方工作正常。 I've even tried using settings.MEDIA_ROOT because I know it works, but still nothing is saved there.我什至尝试过使用settings.MEDIA_ROOT因为我知道它可以工作,但那里仍然没有保存任何内容。 But as you can see, I'm starting out super basic and haven't added a query, loops, etc.但正如你所看到的,我从超级基础开始,并没有添加查询、循环等。

My save_pdf() is different than the SO question I linked to because that is what I'm using in other parts of my application and it is saving files fine there.我的save_pdf()与我链接到的 SO 问题不同,因为这是我在应用程序的其他部分中使用的,并且在那里保存文件很好。 I did try what they provided in the SO question, but had the same results with it not saving.我确实尝试了他们在 SO 问题中提供的内容,但结果相同,但没有保存。 That being:那就是:

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

So what do I need to do to get these PDFs to save to disk?那么我需要做什么才能将这些 PDF 保存到磁盘?

Perhaps I need to be using a different library for my needs as django-wkhtmltopdf seems to do a number of things out of the box that I don't want that I'm not clear I can override.也许我需要使用不同的库来满足我的需要,因为django-wkhtmltopdf似乎做了很多我不希望我不知道可以覆盖的开箱即用的事情。

OK, my smooth brain gained a few ripples overnight and figured it out this morning:好吧,我光滑的大脑一夜之间波澜不惊,今天早上想通了:

# 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!')

This saved the PDF to disk and also did not respond with the PDF.这将 PDF 保存到磁盘,并且也没有响应 PDF。 Obviously a minimally functioning example that I can expand on, but at least got those two issues figured out.显然是我可以扩展的最小功能示例,但至少解决了这两个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM