Search code examples
pythondjangohttpresponsexhtml2pdf

Django xhtml2pdf 'HttpResponse' does not have the buffer interface


I'm trying and making some tests for outputting pdfs with Django. I'm using the xhtml2pdf project installed with pip.

I looked at an example for sending a pdf to the browser and succedeed, but when trying with a template of mine, an error appears. It reads:

'HttpResponse' does not have the buffer interface

My view code is next:

def generate_pdf(request):

    from xhtml2pdf import pisa
    from person.views import alumn_list

    html = alumn_list(request, 12, 0) # This function returns a render('alumn_list.html)

    pdfFile = open(os.path.join(base.TEMPLATE_DIRS[0], 'test.pdf'), 'w+b')
    pisaStatus = pisa.CreatePDF(html, dest=pdfFile) # The errors happens here

    pdfFile.seek(0)
    pdf = pdfFile.read()
    pdfFile.close()
    return HttpResponse(pdf, content_type='application/pdf')

My template is next:

{% extends "alumns.html" %}
{% load i18n %}

{% block extra_css %}
    <style>
    @page {
        size: letter portrait;
        @frame header_frame {           /* Static frame */
            -pdf-frame-content: header_content;
            left: 50pt; width: 512pt; top: 50pt; height: 40pt;
        }
        @frame col1_frame {             /* Content frame 1 */
            left: 44pt; width: 445pt; top: 90pt; height: 632pt;
            text-align:center;
        }

        @frame footer_frame {           /* Static frame */
            -pdf-frame-content: footer_content;
            left: 50pt; width: 512pt; top: 772pt; height: 20pt;
        }
    }
    </style>
{% endblock extra_css %}

{% block title %}
    {% trans "Alumn list" %}
{% endblock title %}

{% block page_title %}
    {% trans "Alumn list" %}
{% endblock page_title %}

{% block content %}
    <table class="infoTable">
        {% csrf_token %}
        {% for index in "12" %}
        <caption {% ifequal index "2" %}align="bottom"{% endifequal%}>
            <a href="{{hrefs.0}}" class="pager">&lt;&lt; {% trans "Previous" %}</a>
            <a href="{{hrefs.1}}" class="pager">{% trans "Next" %} &gt;&gt;</a>
        </caption>
        {% endfor %}

        <thead>
            <th>{% trans "ID" %}</th>
            <th>{% trans "Name" %}</th>
        </thead>
    {% for alumn in alumnList %}
        <tr id="alumn{{alumn.alumnId}}">
            <td>{{ alumn.alumnId }}</td>
            <td><button class="profileAlumn" alumn_id="{{alumn.alumnId}}">{% trans "Profile" %}</button></td>
            <td><button class="deleteAlumn" alumn_id="{{alumn.alumnId}}">{% trans "Delete" %}</button></td>
        </tr>
    {% endfor %}
    </table>
{% endblock content %}

I don't know how to mend this bug. I googled for this error but only three ambiguous pages of results appeared, none making reference to HttpResponse.

Please help. I don't know what I'm doing wrong.

It would help me also if someone has some link where I can learn how to make a pdf from every rendered HTML template from my webapp.

Thanks very much in advance


Solution

  • alumn_list is a view. So it returns an HttpResponse object. But you need to pass a byte string to pisa.CreatePDF which is response's content. So you could do the following:

    pisaStatus = pisa.CreatePDF(html.content, dest=pdfFile)