Part of the benefit of using the web framework Django is the plethora of apps and code available for it. The core Django framework is stable, well written and well documented, but just as importantly has an active community.
We’ve been doing more Django development at Sensible Development of late and decided it’s time to try and give back to the Django community. So we are open-sourcing two Django apps. One app (django-publish) is for adding a “publisher workflow” to Django. It’s been quietly available on github for a while. However it’s the second app that will be discussed here.
Django Sendfile is a very simple app. It has a small focus – to make serving large files in Django easier.
Generally speaking in Django it is recommended to offload the serving of media files to the webserver (e.g. Apache). This frees up Django from doing such mundane work. However this also means that Django can’t get involved. We can’t check permissions from a database for example. So if we have had some large PDF files that we only want to make available to people who have logged, then it is tempting to check the permissions in Django and then serve the file from Django too. This might not be too bad if the files are small, but for larger files things will start to slow down.
So wouldn’t it be great if Django could handle checking permissions, but could then hand over the actual file to the webserver to deal with? Well it’s a pretty common to want to do this, so there are several ways this can be done.
These are obviously all dependant on the server you are running, but more or less do the same thing.
During development though you don’t always want to run a full webserver. So it’s a bit annoying if you then can’t test files downloads.
If you’re a good developer you’ll have some way of abstracting this, so most of your code won’t need to know how you are handling downloads. We needed to create this abstraction and as it’s pretty simple it seemed silly not to share it with the world.
Django Sendfile provides a single function
sendfile which you can use to trigger your webserver to send the contents of a file:
from sendfile import sendfile # send myfile.pdf to user return sendfile(request, '/home/john/myfile.pdf') # send myfile.pdf as an attachment (with name myfile.pdf) return sendfile(request, '/home/john/myfile.pdf', attachment=True) # send myfile.pdf as an attachment with a different name return sendfile(request, '/home/john/myfile.pdf', attachment=True, attachment_filename='full-name.pdf')
Your code only needs to worry about calling sendfile and then you can just configure the relevant backend as you need to. There are currently three configurable backends:
- development – just for development of course
It wouldn’t be hard to add a backend for nginx too and we probably will in the future.
There’s more detail in the README at the django-sendfile repository on github.