Использование ReportLab для создания PDF-файла с последующим сохранением его в пользовательской модели - PullRequest
0 голосов
/ 29 мая 2020

В течение нескольких дней я пытался заставить это работать, и, хотя я думаю, что приближаюсь, я все еще не получил его.

У меня есть функция, которая использует ReportLab для создания PDF-файла SimpleDocTemplate и Я хочу вернуть его в вызывающее представление, чтобы сохранить его в модели профиля uesrs.

Пока это мой код:

model.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'

utils:

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)

Спасибо

1 Ответ

1 голос
/ 29 мая 2020

Во-первых, есть ответ. В дополнение к этим ответам вам нужно прочитать this , просто работать с массивом buffer.getvalue() байтов и использовать класс ContentFile, чтобы сохранить это в поле модели.

Чтобы упростить работу с объектом Response, используйте FileResponse .

- EDIT -

Вам нужно записать ваш pdf в буфер:

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

И я нашел эти инструкции в документации.

Чтобы сохранить PDF в Profile:

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