Reusable apps using “Eight Spaces” - Klaas van Schelven (djangocon.eu)

Tags: djangocon, django

(I’ve got a summary about an earlier talk he gave about this, btw).

He works for legalsense and makes sites for lawyers. Lots of smaller websites. Every website has small differences, which is relevant to this talk.

Django is great. It is modular, but integrated. Views, models, model admins, all tied together.

This talk is about reuse, but he doesn’t mean the framework-y stuff that django already does like south, model fields, template tags. It means reuse of apps.

What is an app? Something with a models.py, a couple of templates, an admin.py, urls a couple of views. That’s what we mean with an app as programmers. The customer doesn’t have this view. A customer sees “a blog” and “a customer list”. Things the customer can touch.

Reusing apps is a recurring theme. Perhaps it is even the holy grail.

Changing an app is often a part of reuse. So you need to change something in an app. For instance you want to add a Dutch social security number to django-authentication. None of their clients want to do that, except one. That’s the kind of very local per-site reuse they have to handle.

Adding just one field should not be too hard, right? Well, it is as we’ll see later on.

One part that works well in django regarding reuse is templates. In template directories with a higher preference (for instance the one in your site), you can override an application’s template. Easy as pie.

For other things, the “parameterize everything” solution is often the stated solution. A view function gets a couple of parameters (template=..., model=..., form=...) and you can configure those parameters in the urls.py. But, say you change the model somewhere, you need to change it everywhere. But what we normally do is use python strongest binding mechanism: a simple direct import. from .models import Something. You’re hosed at that point.

Their solution: “eight spaces”. Class based everything. 369 lines of code. Singleton objects with inheritance and with a concept of self.

The code in their reusable apps looks like this:

from .models import Models
from .views import Views

class App(object):
    def __init__(self):
        self.models = Models(self)
        self.views = Views(self)

This is the only place where the imports happen. Later on you can easily change self.models to be something else. The Models class is something that returns the actual models. And it is a class, so its behaviour can be adjusted when you want to change it.

(In the end, most code is indented one level deeper than normally. The actual model code ends up indented eight spaces, hence the name.)

There are problems, though. There’s a certain lack of elegance due to the greater level of indentation and more lines. And you need to explicitly prepare your app this way. Circular imports are a real problem.

Success stories: their customers are happy. The last commit to the code happened half a year ago, so it Just Works. They’re continually using it.

Alternatives? Generic keys could help. Or you’d have to allow for lots more extension points in your apps and build them in from the start.

New sluice construction near Nieuwegein
 
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):