Создание PDF файлов с помощью django (wkhtmltopdf)

Может кто-нибудь, пожалуйста, предоставьте мне исчерпывающий пример того, как получить view в django, чтобы вернуть PDF с помощью wkhtmltopdf. Есть ограниченное число примеров, которые поставляются с django-wkhtmltopdf, и они предполагают уровень знаний, которого у меня просто нет. Я просмотрел исходный код, но я не могу сделать головы или хвосты того, как его использовать (например, какая разница между PDFTemplateView и PDFTemplateResponse?!?)

Буду очень благодарен за любую помощь.

BTW (я также использую шаблоны для верхнего и нижнего колонтитула)

ИЗМЕНИТЬ

def some_view(request,sID):
    something = get_object_or_404(Something,id=sID)
    return render_to_response('something.html', {'something':something}, context_instance=RequestContext(request))

Как мне получить следующий простой вид, чтобы предоставить мне PDF вместо файла html?

РЕДАКТИРОВАТЬ 2

В настоящее время я играю с:

def pdf_view(request,sID):
    template = 'pdf.html'
    something = get_object_or_404(Something,id=sID)
    context = {
        'something' : Something,
        'object_for_header_and_footer': something.object_for_header_and_footer,
    }
    cmd_options = settings.WKHTMLTOPDF_CMD_OPTIONS

    return PDFTemplateResponse(request=request,
        context=context,
        template=template,
        filename='something',
        header_template='header.html',
        footer_template='footer.html',
        cmd_options=cmd_options)

но я получаю 'str' object has no attribute 'update' в /usr/local/lib/python2.7/dist-packages/wkhtmltopdf/utils.py in wkhtmltopdf, line 74. Я не знаю, начинать ли взлом wkhtmltopdf?!?!

Ответ 1

Разница между PDFTemplateView и PDFTemplateResponse заключается в том, что представление представляет собой представление на основе класса. И PDFTemplateResponse отображает данные в формате pdf и устанавливает правильные заголовки ответов . Чтобы добавить верхний и нижний колонтитул:

# urls.py

from django.conf.urls.defaults import *
from wkhtmltopdf.views import PDFTemplateView


    urlpatterns = patterns('',
        ...
        url(r'^pdf/$', PDFTemplateView.as_view(template_name='my_template.html',
                filename='my_pdf.pdf', 
                header_template='my_header_template.html', 
                footer_template='my_footer_template.html', 
                ...
                ), name='pdf'),
    )

Открытие pdf/в вашем браузере начнет загрузку my_pdf.pdf на основе my_template.html, my_header_template.html и my_footer_template.html.

В расширенном примере показано, как подкласс PDFTemplateView расширяет и меняет логику PDFTemplateView. Чтобы понять, что происходит, прочитайте Использование представлений на основе классов.

Подобно header_template и footer_template, вы можете определить response_class. Поскольку PDFTemplateResponse является значением по умолчанию, вам не нужно его определять.

ИЗМЕНИТЬ

Следующее простое представление предоставляет вам pdf вместо html. Это не используется django-wkhtmltopdf. Вы можете использовать wkhtmltopdf в своей функции html2pdf.

def some_view(request):
    t = loader.get_template('myapp/template.html')
    c = RequestContext(request, {'foo': 'bar'})
    html = t.render(c)
    pdf_data = html2pdf(html) # Your favorite html2pdf generator
    response = HttpResponse(pdf_data, content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="some_filename.pdf"'
    return response

РЕДАКТИРОВАТЬ 2

Простой вид с контекстом:

template.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Untitled</title>
</head>
<body>
    <h1>{{ title }}</h1>
</body>
</html>

urls.py

from views import MyPDFView

urlpatterns = patterns('',
    (r'^pdf/', MyPDFView.as_view()),
)

views.py

from django.views.generic.base import View
from wkhtmltopdf.views import PDFTemplateResponse

class MyPDFView(View):
    template='template.html'
    context= {'title': 'Hello World!'}

    def get(self, request):
        response = PDFTemplateResponse(request=request,
                                       template=self.template,
                                       filename="hello.pdf",
                                       context= self.context,
                                       show_content_in_browser=False,
                                       cmd_options={'margin-top': 50,},
                                       )
        return response

РЕДАКТИРОВАТЬ 3

Если вы используете DetailView, вы можете добавить объект в контекст:

url(r'^books/(?P<pk>\d+)/$', MyPDFView.as_view(), name='book-detail'),


class MyPDFView(DetailView):
    template='pdftestapp/template.html'    
    context= {'title': 'Hello World!'}
    model = Book

    def get(self, request, *args, **kwargs):        
        self.context['book'] = self.get_object()

        response=PDFTemplateResponse(request=request,
                                     template=self.template,
                                     filename ="hello.pdf",
                                     context=self.context,
                                     show_content_in_browser=False,
                                     cmd_options={'margin-top': 50,}
                                     )
        return response

Ответ 2

Hmm ошибка указывает, что вы передаете строку где-то, что вам не нужно.

После проверки исходного кода, я думаю, что в settings.py у вас есть WKHTMLTOPDF_CMD_OPTIONS как строка, что-то вроде

WKHTMLTOPDF_CMD_OPTIONS = 'some_option_here'

Но вы должны назначить там dict:

WKHTMLTOPDF_CMD_OPTIONS = {
    'quiet': True,
}

В противном случае ваш код должен работать нормально.