Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a multi-table inheritance design generic in Django

First of all, some links to pages I've used for reference: A SO question, and the Django docs on generic relations and multi-table inheritance.

So far, I have a multi-table inheritance design set up. Objects (e.g: Car, Dog, Computer) can inherit an Item class. I need to be able to retrieve Items from the DB, get the subclass, and do stuff with it. My design doesn't allow for retrieving the different kinds of objects one by one, so I need to use the Item container to wrap them all into one. Once I have the Item, the Django docs say I can get the subclass by referencing the attribute with the name of the model (e.g: myitem.car or myitem.computer).

I don't know which type of object my item is referencing, so how can I get the child? Is there a built in way to do this? Here are some other ideas that I had: (some crazier than others)

  1. I was thinking I could add some sort of GenericForeignKey to Item that references the child, but I doubt it is even legal for a parent class to relate via a ForeignKey to a child class.
  2. I suppose I could have a ForeignKey(ContentType) in the Item class, and find the attribute of Item to get the child based on the ContentType's name.
  3. Finally, although an ugly method, I might be able to keep a list of object types, and try each as an attribute until a DoesNotExist error is not thrown.

As you can see, these proposed solutions are not that elegant, but I'm hoping I won't have to use one of them and someone here might have a better suggestion.

Thanks in advance

like image 724
Cory Walker Avatar asked Nov 11 '09 02:11

Cory Walker


People also ask

What are the methods of inheritance in Django?

There are three styles of inheritance possible in Django. Abstract base classes: Use this when the parent class contains common fields and the parent class table is not desirable. Multi-table inheritance: Use this when the parent class has common fields, but the parent class table also exists in the database all by itself.

What is multi-table inheritance in SQL?

Multi-table inheritance: Use this when the parent class has common fields, but the parent class table also exists in the database all by itself. Proxy models: Use this when you want to modify the behavior of the parent class, like by changing orderby or a new model manager.

Can a child class override a model field in Django?

In normal Python class inheritance, it is permissible for a child class to override any attribute from the parent class. In Django, this isn’t usually permitted for model fields.

Why can’t I create another model field called author in Django?

In Django, this isn’t usually permitted for model fields. If a non-abstract model base class has a field called author, you can’t create another model field or define an attribute called author in any class that inherits from that base class. This restriction doesn’t apply to model fields inherited from an abstract model.


1 Answers

I have done something similar to method 2 in one of my projects:

from django.db import models
from django.contrib.contenttypes.models import ContentType

class BaseModel(models.Model):
    type = models.ForeignKey(ContentType,editable=False)
    # other base fields here

    def save(self,force_insert=False,force_update=False):
        if self.type_id is None:
            self.type = ContentType.objects.get_for_model(self.__class__)
        super(BaseModel,self).save(force_insert,force_update)

    def get_instance(self):
        return self.type.get_object_for_this_type(id=self.id)
like image 107
Wogan Avatar answered Oct 17 '22 20:10

Wogan