Figuring out proper django packaging

Tags: django

First week at the new job, so I get do delve into currently-unkown code. And I get to reload my Django knowledge back into my head: it has been a year since I “did” my till-now-only-one django project.

And I got the job of introducing proper python packaging.

Proper packaging

“Proper python packaging” for me means two things:

  • Every piece of software is a python package. So something with a setup.py that you can easy_install.

  • You manage your packages (in the projects/sites/whatever where you use them) with buildout. See for instance my managing dependencies article, especially the “isolation and version handling” part. That’s what buildout is good at: isolating your environment and grabbing just the right set of packages. (In the Django context, you’ll want to read Jacob Kaplan-Moss’s introduction).

In the Django context I’d add one more aspect to proper packaging:

  • Use packages a lot. Take your axe and chop up your code. Every django application should do just one thing and do it well, see James Bennett’s video on building reusable apps. So take your big monolithic project and chop it up in properly-sized packages.

Advantages of packaging

Without packaging, you basically end up with one directory structure for your project. One main directory and the libraries (Django: applications) inside it. When you take those libraries and package them independently, you get several advantages:

  • If you use such a package in multiple projects, you can just do that. No need to copy-paste code. Reusability. Especially welcome when you keep your packages small, tight and focused.

  • A bit of formalization: the setup.py contains the name of the package, the version number, a short explanation.

  • One of the best things: specifying your dependencies! No more delving through a README to figure out what you need to install: it gets pulled in automatically.

  • A bit of documentation is easy. Perhaps a minor point, but a package has a so-called long_description. It is customary to take the readme, changelog and possible other files and use those as long description. Basically what you see on the pypi page of a project (but usable outside pypi of course). For me, the “it is customary” is what helps.

No namespaces in Django

Coming from a Zope and Plone background, I’m used to packages like zest.releaser, plone.app.something, z3c.anotherthing. Namespaces. Handy to keep zest.releaser out of collective.releaser’s hair. And to keep the generic openid package, plone’s openid package and your company’s openid package out of each others hair: you cannot call all of them “openid”.

We’ve got two main product lines at our company. And the first subdirectory that I tackled was called “base”. So firstproductline.base was born.

Raargh, Django doesn’t like namespaces. You get errors like “application firstproductline not found” when you expect it to load “firstproductline.base”. And from what I read, namespaces are actively discouraged in Django.

So what I settled with, after some googling for examples, was to name the package firstproductline-base (with a dash). The svn url is something like https://.../firstproductline-base/trunk. And inside that, the actual code is in a firstproductline_base directory (with an underscore). firstproductline_base is thus the module name that you import.

Well, I’ll have to see how well such a scheme holds up. Feedback welcome!

 
vanrees.org logo

Reinout van Rees

My name is Reinout van Rees and I program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.

Weblog feeds

Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):