如何将使用 BytesIO 创建的 PDF 文件添加到 Django 模型中的 FileField 中

How to add PDF file created with BytesIO into a FileField in a model of Django

我可以在 Django 应用程序中使用 reportlab 创建 PDF 文件。但是,我无法将它添加到模型中的 FileField 中。我想知道如何将 io.BytesIO 数据传输到 Django 中的 FileField。

这是我的总结 views.py。

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.pdfbase import pdfmetrics

buffer = io.BytesIO()
cc = canvas.Canvas(buffer, pagesize=A4)

# describe something
font_name = "HeiseiKakuGo-W5"
cc.registerFont(UnicodeCIDFont(font_name))
cc.setFont(font_name, 7)
cc.drawString(65*mm, 11*mm, 'test')

cc.showPage()
cc.save()
buffer.seek(0)

exampleObject= get_object_or_404(SomeModel, pk=self.kwargs['pk'])
exampleObject.exampleFileField.save('test.pdf', File(buffer)) # here! this sentence doesn't work.
exampleObject.save()

return FileResponse(buffer, as_attachment=True, filename='test.pdf')

关键是下面这句话是行不通的。我认为“文件(缓冲区)”不合适。

exampleObject.exampleFileField.save('test.pdf', File(buffer))

虽然在目录中创建 pdf 文件作为临时文件后,我尝试将 pdf 保存到 FileField 中,但我更喜欢使用 io.BytesIO.

您可能需要 seek(0) 在您的 buffer 上,因为它以前被使用过,我不会感到惊讶缓冲区会在最后并导致在 Django 中保存一个空文件.

我相信你的失踪buffer.get_value()

我也使用 ContentFile 而不是 File,但不确定是否有必要。

我刚刚测试了以下代码片段,它可以使用 reportlab==3.5.32

import io

from django.core.files.base import ContentFile
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

from my_app.models import MyModel

buffer = io.BytesIO()
canv = canvas.Canvas(buffer, pagesize=A4)
canv.drawString(100, 400, "test")
canv.save()
pdf = buffer.getvalue()
buffer.close()

my_object = MyModel.objects.latest("id")
my_object.file_field.save("test.pdf", ContentFile(pdf))