Submit Blog  RSS Feeds

Monday, April 23, 2012

Django view serving dynamically generated PDF files.

Serving static files is cool. However, static files have a drawback - mainly they tend to be static. I'm not saying that you should avoid serving static content or anything similar - static files have variety of important applications , which are not the topic of this post.

So what can you do when you want to serve a dynamically generated PDF file to the user? First of all you have to provide a package capable of generating such files, so unless you want to spend quite a few days implementing your own tool, you should try using ReportLab. ReportLab is quite powerful, but it takes a lot of effort to create a good layout. If you also want your PDF file to look sexy - you should choose pisa (it requires ReportLab as a dependency). Pisa is a HTML/CSS to PDF converter - which is just what we need (be warned - not all CSS styles are supported, but that's another history).

Let's have a look at this code:


  1 import ho.pisa
  2 import cStringIO
  3
  4 from django.http import HttpResponse
  5 from django.template.loader import get_template
  6 from django.template import Context
  7
  8    
  9 def generate_pdf(template_file, context={}):
 10     #to avoid using a temporary file StringIO has to be used
 11     pdf = cStringIO.StringIO()
 12     template = get_template(template_file)
 13    
 14     html_response  = template.render(Context(context))
 15    
 16     pdf_status = ho.pisa.pisaDocument(cStringIO.StringIO(html_response), pdf)
 17    
 18     if pdf_status.err:
 19         #catch it in the invoking view
 20         raise Exception('Oops! Something went wrong!')
 21     return HttpResponse(pdf.getvalue(), mimetype='application/pdf')
 

 This is a generic function that can render any template with an apropriate context and return a HttpResponse, this function may be used the following way:

 24 def generate_report_view(request):
 25     '''
 26         (...) some code
 27     '''
 28     return generate_pdf('reports/sample_report.html',\
 29         {'owner' : request.user, 'some_param' : 'Hello PDF Generator'})


There are two tricks here, that enable downloading the generated PDF directly from the view. Firstly, the cStringIO (faster version of StringIO) is used instead of a file, so that we do not have to make any HDD IO operations. Secondly we set the response mimetype to application/pdf, which informs a browser that this is not a regular site.

~KR

1 comment:

  1. Hi krizy,

    This is Manu, can you please tell me how to deploy django project in apache server on windows?
    if it possible can you please share details to my mail.My mail id is " manu.cmh@gmail.com"

    Thanks in advance

    ReplyDelete

free counters