【问题标题】:How to Save io.BytesIO pdfrw PDF into Django FileField如何将 io.BytesIO pdfrw PDF 保存到 Django FileField
【发布时间】:2020-05-27 06:09:03
【问题描述】:

我想做的基本上是:

  1. 从 URL 获取 PDF
  2. 通过pdfrw修改
  3. 将其存储在内存中 一个 BytesIO 对象
  4. 通过以下方式将其上传到 Django FileField Model.objects.create(form=pdf_file, name="Some name")

我的问题是,当create() 方法运行时,它会保存form 的所有字段除了。

helpers.py

import io
import tempfile
from contextlib import contextmanager

import requests
import pdfrw


@contextmanager
def as_file(url):
    with tempfile.NamedTemporaryFile(suffix='.pdf') as tfile:
        tfile.write(requests.get(url).content)
        tfile.flush()
        yield tfile.name


def write_fillable_pdf(input_pdf_path, output_pdf_path, data_dict):
    template_pdf = pdfrw.PdfReader(input_pdf_path)

    ## PDF is modified here

    buf = io.BytesIO()
    print(buf.getbuffer().nbytes). # Prints "0"!
    pdfrw.PdfWriter().write(buf, template_pdf)
    buf.seek(0)
    return buf

views.py

from django.core.files import File

class FormView(View):
    def get(self, request, *args, **kwargs):
        form_url = 'http://some-pdf-url.com'

        with as_file(form_url) as temp_form_path:
            submitted_form = write_fillable_pdf(temp_form_path, temp_form_path, {"name": "John Doe"})
            print(submitted_form.getbuffer().nbytes).  # Prints "994782"!
            FilledPDF.objects.create(form=File(submitted_form), name="Test PDF") 
        return render(request, 'index.html', {})

如您所见,print() 在填充 BytesIO 时给出了两个不同的值,这让我相信大小的增加意味着其中实际上有数据。是否有原因无法正确保存到我的 django 模型实例中?另外,如果有人知道更有效的方法,请告诉我!

【问题讨论】:

    标签: python django pdf bytesio pdfrw


    【解决方案1】:

    您可以在代码中使用ContentFile 类。我在您的视图中进行了相应的修改,以将您的文件保存在文件字段中。

    from django.core.files.base import ContentFile
    
    class FormView(View):
        def get(self, request, *args, **kwargs):
            form_url = 'http://some-pdf-url.com'
    
            with as_file(form_url) as temp_form_path:
                submitted_form = write_fillable_pdf(temp_form_path, temp_form_path, {"name": "John Doe"})
                pdf_content = ContentFile(submitted_form.getvalue(), 'sample.pdf')
                FilledPDF.objects.create(form=pdf_content, name="Test PDF") 
            return render(request, 'index.html', {})
    

    您还可以使用save 方法使用ContentFile 类存储文件。

    from django.core.files.base import ContentFile
    
        class FormView(View):
            def get(self, request, *args, **kwargs):
                form_url = 'http://some-pdf-url.com'
    
                with as_file(form_url) as temp_form_path:
                    submitted_form = write_fillable_pdf(temp_form_path, temp_form_path, {"name": "John Doe"})
                    pdf_content = ContentFile(submitted_form.getvalue())
                    filled_pdf = FilledPDF()
                    filled_pdf.name = "Test PDF"
                    filled_pdf.form.save("sample.pdf", pdf_content, save=False)
                    filled_pdf.save()
                return render(request, 'index.html', {})
    

    【讨论】:

    • 不幸的是这不起作用:(我的模型实例保存了,但“表单”字段显示没有上传文件
    • @Hybrid,忘记在ContentFile 实例中添加文件名。更新它并添加另一种存储文件的方式。这将起作用。 :)
    • 谢谢!看起来文件没有以正常方式保存,因为我忘记了文件名。
    【解决方案2】:

    这是how to save a file to an object 上的文档。

    from django.core.files import File
    
    filled_pdf = FilledPDF()
    filled_pdf.form.save('test_pdf.pdf', File(submitted_form.getvalue()), save=True)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 2010-10-25
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多