【问题标题】:Using ReportLab To Create A PDF Then Save It To A User Model使用 ReportLab 创建 PDF,然后将其保存到用户模型
【发布时间】:2020-05-29 23:13:23
【问题描述】:

几天来,我一直在努力让它工作,虽然我认为我已经接近了,但我仍然没有让它工作。

我有一个使用 ReportLab 生成 SimpleDocTemplate pdf 的函数,我想将其返回到调用视图,以便将其保存到 uesrs Profile 模型。

这是我目前的代码:

模型.py

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    profile_pdf = models.FileField(upload_to='pdfs/user_pdfs')

错误信息:

'HttpResponse' object has no attribute 'read'

查看

def final_question(request):
    if request.method == 'POST':
        # this is the final form they complete
        form = FinalQuestionForm(request.POST, request.FILES, instance=request.user.finalquestion)

        if form.is_valid():
            form.save()

            # generate pdf containing all answers to enrolment questions
            users_pdf = utils.generate_user_pdf(request)

            # here i get the users model
            # hard coded user_id for testing
            users_profile = Profile.objects.get(user_id=1)
            # then i get the field I want to save to
            pdf = users_profile.profile_pdf
            # then i save the generated pdf to the field
            pdf.save('user_1_pdf', users_pdf)

我的pdf生成函数

def generate_user_pdf(request):
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename = "test.pdf"'

    doc = SimpleDocTemplate(response)

    elements = []

    data= [
                 ['---TEST DATA---'],
                 ['test data'],
          ]

    [.. cont ..]

    doc.build(elements)

    return response

谢谢。

--编辑--

错误:

argument should be a bytes-like object or ASCII string, not 'FileResponse'

实用程序:

def generate_pdf(request):
    buffer = io.BytesIO()

    doc = SimpleDocTemplate('test')
    story = []

    doc.build(story)

    response = FileResponse(buffer.getvalue())

    return response

views.py

# generate pdf containing all answers
            user_pdf = utils.generate_pdf(request)

            # get users enrolment_pdf field
            # temp hard-coded
            user_profile = Profile.objects.get(user_id=1)
            field = user_profile.user_pdf

            # save the generated pdf to the user in the database
            file_data = ContentFile(base64.b64decode(user_pdf))
            field.save('test', file_data)

谢谢

【问题讨论】:

    标签: python django reportlab


    【解决方案1】:

    首先,there is 一个答案。 除了这个答案,您还需要阅读this,只需使用buffer.getvalue() 字节数组并使用ContentFile 类将其保存到模型字段。

    要简化使用 Response 对象的工作,请使用 FileResponse

    --编辑--

    您需要将 pdf 写入缓冲区:

    doc = SimpleDocTemplate(buffer)
    doc.build(story)
    buffer.seek(0)
    pdf: bytes = buffer.getvalue()
    return FileResponse(pdf, filename='doc.pdf')
    

    而且,我在文档中找到了 these 说明。

    将pdf保存到Profile

    file_data = ContentFile(pdf)
    profile = Profile.objects.get(...)
    profile.pdf_field.save('filename.pdf', file_data, save=False)
    profile.save()
    

    【讨论】:

    • 非常感谢。抱歉我的迟钝,我很难理解很多这些东西。我阅读了您链接的页面并将其实现到我的代码中(我在上面的编辑下提供了它)。我(想我)理解错误消息,虽然我很困惑,因为我必须返回 FileResponse、HttpRequest 或类似的东西,但我不知道如何将它传递给“类似字节的对象”。如果你能在正确的方向上再给我一次推动,我将不胜感激。谢谢
    • 别担心,我们都是从这里开始的。添加了 EDIT 内联。
    • 并且不要忘记使用唯一名称调用您的文件,例如f'{profile.username}.pdf'
    • 非常感谢。这远远超出了我的能力,如果没有你的帮助,我永远不会做到这一点。它现在有效,明天我将剖析它并理解/学习它。再次感谢:)
    猜你喜欢
    • 2015-02-26
    • 1970-01-01
    • 2015-10-20
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    相关资源
    最近更新 更多