The Django ORM Does Not Support Classical Inheritance
23rd of January 2009After encountering difficulties installing CouchDB on Webfaction (Still a work in progress - let me know if you've had success!) I decided to try and back port some of my CouchDB refactor to the Django ORM. I'd not really used any of the model inheritance functionality, so assumed it would follow the classical pythonic inheritance model. Unfortunately it seems that instead the Django team have decided to use a lesser form using a 'has a' relationship instead of the traditional 'is a'.
What this means in practice is that subclasses, while accessible through the managers of their superclasses, are not first class citizens. Thus, the example in the django documentation:
>>> p = Place.objects.filter(name="Bob's Cafe")
# If Bob's Cafe is a Restaurant object, this will give the child class:
>>> p.restaurant
<Restaurant: ...>
Here you can see that, rather than restaurant being a specialised version of place, it is in fact a separate entity with a one to one mapping between the two. This, I guess, was the reason behind the team choosing to implement this form of inheritance - it maps to the RDBS model very smoothly. It is also the reason I fundamentally disagree with it - ORM's are designed to abstract the database to make the interface more like the language. In this situation, the ORM has chosen to be less pythonic in order to keep the backend implementation more simple.
The consequences are quite annoying. What I want is to have a generic, but not abstract, model, and certain specialisations of this model. I wish to be able to override the subclasses to provide different fuctionality. Specifically - I wish to have a generic Article class that will store postings to my website, but subclass it when further funcionality is required, for example when posting a photo. In this situation, the content attribute has a different semantic meaning. I wish to generate the content from the other attributes in the case of the Photo.
Unfortunately, with the way inheritance is implemented in Django, I cannot simply override the content property in my Photo model. Because the extra data is only stored in the Photo table, I either have to check whether each instance is a photo in all of my views so I can use the relationship to access the method (which violates the duck typing principle) or I have to have Photo specific logic within my Article model (violating encapsulation). It is unfortunate that this is the way it has been implemented. I'm going to try and find a workaround, because neither of these situations are satisfactory.

