Search code examples
pythondjangopdfpopenwkhtmltopdf

Returning a PDF response in Django


I'm asking a very similar question to this one. I'm creating a pdf using wkhtmltopdf on an Ubuntu server in Django.

from tempfile import *
from subprocess import Popen, PIPE

tempfile = gettempdir()+"/results.pdf"
papersize = 'Tabloid'
orientation = 'Landscape'
command_args = "wkhtmltopdf -O %s -s %s -T 0 -R 0 -B 0 -L 0 http://pdfurl %s" %(orientation, papersize, tempfile)
popen = Popen(command_args, stdout=PIPE, stderr=PIPE)
pdf_contents = popen.stdout().read()
popen.terminate()
popen.wait()
response = HttpResponse(pdf_contents, mimetype='application/pdf')
return response

This gives me a "no such file or directory" error on the popen = Popen... line. So I changed that line to

popen = Popen(["sh", "-c", command_args], stdout=PIPE, stderr=PIPE)

and now I get a "'file' object is not callable" error on the pdf_contents =... line.

I've also tried adding .communicate() to the popen =... line but I can't seem to locate the pdf output that way. I should add that typing the command_args line into the command line creates a pdf just fine. Can anyone point me in the right direction?


Solution

  • Your first version fails because python does not know where wkhtmltopdf is located. Python will not check your path for that. Your second version passes the command to a shell which takes care of that. You achieve the same effect by passing a shell=True argument.

    The second problem (as others have noted) is that you call stdout() when you shouldn't.

    The third problem is that your wkhtmltopdf command is wrong. You are doing:

    wkhtmltopdf -O %s -s %s -T 0 -R 0 -B 0 -L 0 http://pdfurl tempfile/results.pdf
    

    Instead you should pass

    wkhtmltopdf -O %s -s %s -T 0 -R 0 -B 0 -L 0 http://pdfurl -
    

    That way wkhtmltopdf will write the output to standard output and you can read it. If you pass another - as the source, you can send the html over the standard input.