2013-08-14 41 views
11

Có thể ai đó vui lòng cung cấp cho tôi một ví dụ toàn diện về cách lấy view trong django để trả lại PDF sử dụng wkhtmltopdf. Có một số ví dụ giới hạn đi kèm với django-wkhtmltopdf và chúng giả định mức độ kiến ​​thức mà tôi không có. Tôi đã xem xét mã nguồn nhưng tôi không thể làm cho đầu hoặc đuôi của cách sử dụng nó (ví dụ như whats sự khác biệt giữa PDFTemplateViewPDFTemplateResponse?!?)Tạo các tệp PDF với django (wkhtmltopdf)

Tôi sẽ rất biết ơn sự giúp đỡ nào.

BTW (Tôi đang sử dụng mẫu cho các header và footer cũng)

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

Làm thế nào tôi sẽ có được cái nhìn đơn giản sau đây để cung cấp cho tôi với một pdf thay của một tệp html?

EDIT 2

Tôi hiện đang chơi xung quanh với:

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) 

nhưng tôi nhận được 'str' object has no attribute 'update' trong /usr/local/lib/python2.7/dist-packages/wkhtmltopdf/utils.py in wkhtmltopdf, line 74. Tôi không biết có bắt đầu hack wkhtmltopdf không?!?!

+1

Chế độ xem thông thường và PDFTemplateResponse đang hoạt động đối với tôi. Tôi đã không chỉ định WKHTMLTOPDF_CMD_OPTIONS. – allcaps

Trả lời

17

Sự khác biệt giữa PDFTemplateView và PDFTemplateResponse là chế độ xem là chế độ xem dựa trên lớp. Và PDFTemplateResponse hiển thị dữ liệu pdf và đặt đúng response headers. Để thêm header và footer:

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

Mở pdf/trong trình duyệt của bạn sẽ bắt đầu tải về của my_pdf.pdf dựa trên my_template.html, my_header_template.html và my_footer_template.html.

advanced example cho biết cách phân lớp PDFTemplateView mở rộng và thay đổi logic của PDFTemplateView. Để hiểu điều gì xảy ra, hãy đọc Using class based views.

Giống như header_templatefooter_template bạn có thể xác định response_class. Vì PDFTemplateResponse là mặc định, bạn không cần phải xác định nó.

EDIT

Quan điểm đơn giản sau đây cung cấp cho bạn với một pdf thay vì một html. Đây không phải là sử dụng django-wkhtmltopdf. Bạn có thể sử dụng wkhtmltopdf trong hàm html2pdf của mình.

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

Một cái nhìn đơn giản với bối cảnh:

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

Nếu bạn sử dụng DetailView, bạn có thể thêm các đối tượng để bối cảnh:

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

Đó là tốt cho rendering '.html' tĩnh (tôi đoán) nhưng những gì sẽ xảy ra nếu bạn muốn' def something.views.something_view (request, someID) 'để render một' pdf' thay vì sau đó 'html'? – Sevenearths

+0

(và trên một mặt lưu ý lý do tại sao các tệp '* .html' tĩnh được chuyển đến các thuộc tính với' mẫu' trong chúng. Nó không có ý nghĩa?!? Chắc chắn nếu một thuộc tính có 'mẫu' trong nó, nó yêu cầu một 'view'. Không phải là nó?!?) – Sevenearths

+1

Tôi cảm thấy một chút như' User.objects.filter (clue__lt = 0) ' – Sevenearths

2

Hmm lỗi chỉ ra rằng bạn đang đi qua chuỗi ở đâu đó mà bạn không nên.

Sau khi kiểm tra source code của nó, tôi đoán trong settings.py bạn có WKHTMLTOPDF_CMD_OPTIONS như là một chuỗi, một cái gì đó giống như

WKHTMLTOPDF_CMD_OPTIONS = 'some_option_here' 

Nhưng bạn nên gán một dict có:

WKHTMLTOPDF_CMD_OPTIONS = { 
    'quiet': True, 
} 

Nếu mã của bạn sẽ làm việc tốt .

Các vấn đề liên quan