2013-08-14 13 views
11

Czy mógłby mi ktoś podać kompleksowy przykład, jak uzyskać view w django, aby zwrócić PDF przy użyciu wkhtmltopdf. Istnieje ograniczona liczba przykładów, które pochodzą z django-wkhtmltopdf i zakładają poziom wiedzy, którego po prostu nie mam. Przejrzałem kod źródłowy, ale nie potrafię wyłowić ani głowy, jak go używać (na przykład jaka jest różnica między PDFTemplateView a PDFTemplateResponse?!?)Tworzenie plików PDF za pomocą django (wkhtmltopdf)

Byłbym bardzo wdzięczny za każdą pomoc.

BTW (używam szablonów dla nagłówka i stopki, jak również)

EDIT

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)) 

Jak bym się następujący prosty pogląd, aby zapewnić mi z pdf zamiast pliku html?

EDIT 2

Jestem obecnie zabawy z:

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) 

ale jestem coraz 'str' object has no attribute 'update' w /usr/local/lib/python2.7/dist-packages/wkhtmltopdf/utils.py in wkhtmltopdf, line 74. Nie wiem, czy zacząć hackowanie wkhtmltopdf?!?!

+1

Normalny widok i PDFTemplateResponse działa dla mnie. Nie określiłem WKHTMLTOPDF_CMD_OPTIONS. – allcaps

Odpowiedz

17

Różnica między PDFTemplateView i PDFTemplateResponse polega na tym, że widok jest widokiem klasowym. Natomiast PDFTemplateResponse renderuje dane w formacie pdf i ustawia odpowiednio response headers. Aby dodać nagłówek i stopkę:

# 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'), 
    ) 

Otwarcie pdf/w swojej przeglądarce rozpocznie pobieranie my_pdf.pdf oparciu o my_template.html, my_header_template.html i my_footer_template.html.

W artykule advanced example pokazano sposób podklasy PDFTemplateView rozszerzającej i zmieniającej logikę PDFTemplateView. Aby zrozumieć, co się dzieje, przeczytaj Using class based views.

Podobnie jak header_template i footer_template można zdefiniować response_class. Ponieważ parametr PDFTemplateResponse jest domyślny, nie trzeba go definiować.

EDIT

Poniższy prosty View umożliwia Ci pdf zamiast html. To nie używa django-wkhtmltopdf. Możesz użyć wkhtmltopdf w swojej funkcji 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 

EDIT 2

prosty widok z kontekstu:

template.html

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

URL.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 

EDIT 3

Jeśli używasz DetailView można dodać obiekt do kontekstu:

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 
+0

To jest w porządku do renderowania statycznego '.html' (przypuszczam), ale co się stanie, jeśli chcesz' def something.views.something_view (request, someID) 'do renderowania' pdf' zamiast 'html'? – Sevenearths

+0

(i na marginesie, dlaczego statyczne pliki '* .html' są przekazywane do atrybutów z' template' w nich nie ma sensu?!? Z pewnością jeśli atrybut ma w sobie 'template', to prosi o "widok". Czy to nie jest?!?) – Sevenearths

+1

Czuję się trochę jak "User.objects.filter (clue__lt = 0)" – Sevenearths

2

Hmm błąd wskazuje, że przekazujesz ciąg gdzieś, czego nie powinieneś.

Po sprawdzeniu jego source code Chyba w settings.py masz WKHTMLTOPDF_CMD_OPTIONS jako ciąg znaków, coś

WKHTMLTOPDF_CMD_OPTIONS = 'some_option_here' 

Ale należy przypisać dict tam:

WKHTMLTOPDF_CMD_OPTIONS = { 
    'quiet': True, 
} 

przeciwnym razie kod powinien działać dobrze .

Powiązane problemy