Packaging a Django reusable app

May 5, 2010 Tags: django, python, packaging

I suck less at packaging.

Yesterday I released an update on Pypi for a Django reusable app I wrote: django-geoportail. Actually, I released two updates because the first one wasn't fully operational and it makes me think all the previous releases weren't either. First lesson learned: check the packages you upload to pypi actually work.

So, I had to learn the hard way how to package a Django app. The biggest difference with a standard python package is that you may want to include non-python files, such as media files and templates. Let's have a look at a basic

# -*- coding: utf-8 -*-
from distutils.core import setup

    author=u'Bruno ReniƩ',
    license='BSD licence, see LICENCE.txt',
    description='Add maps and photos from the French National Geographic' + \
                ' Institute to GeoDjango',

And here is the structure of what I want to package:

|-- forms
|   |--
|   |--
|   `--
|-- templates
|   |-- geoportal
|   |   |-- map.html
|   |   `-- widget.html
|   `-- gis
|       `-- admin
|           |-- geoportal.html
|           `-- geoportal.js
|-- templatetags
|   |--
|   `--

I was naively thinking that having packages=['geoportal'] in plus including the static files in a file would magically include everything. Well, the template files are included in the source distribution, but they are skipped at the time of the installation. Even worse, sub-packages are skipped as well, leaving me without the forms and the templatetags directories.

The solution for including sub-packages is to use find_packages:

from distutils.core import setup
from setuptools import find_packages

    # ...

find_packages will look for every directory containing a file and include it.

Next, the templates. Two things are needed to include them:

  • add include_package_data=True in the setup parameters

  • create a file to declare the files to include:

    recursive-include geoportal *.py *.html *.js
    include docs/Makefile
    recursive-include docs/source *

    Here, I include all the HTML and javascript file under the geoportal directory, the standard authors / changes / readme files and the documentation. During installation, only the files in a python package will be copied to the site-packages. The docs and text files at the root level are just useful for people who manually download the tarball: one unzipped, it provides all the documentation and information about the package.

Finally, I like the zip_safe=False option. It prevents the package manager to install a python egg, instead you'll get a real directory with files in it. I find it very convenient for debugging, when some information can be found by looking at the code.

If you're a packaging expert and think I'm doing anything wrong, I'd like to read your thoughts!

UPDATE 2010-06-08: in the first version of this post, I explained that I didn't understood what the file was for. This is now clarified, include_package_data can only work if some data is included in the file.


August 16, 2010Fabien

Thanks to you, it saved a lot of my time :)

September 3, 2010Jens Hoffmann

Thanks a lot for this quick and good howto!

Add a comment

Comments are closed for this entry.

Short URL