10đź‘Ť
Model inheritance in Django
works almost identically to the way normal class inheritance works in Python, but the basics at the beginning of the page should still be followed. That means the base class should subclass django.db.models.Model
.
The only decision you have to make is whether you want the parent models to be models in their own right (with their own database tables), or if the parents are just holders of common information that will only be visible through the child models.
There are three styles of inheritance that are possible in Django.
1)
Often, you will just want to use the parent class to hold information that you don’t want to have to type out for each child model. This class isn’t going to ever be used in isolation, so Abstract base classes are what you’re after.
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
Edit:
Abstract base classes are useful when you want to put some common information into a number of other models. You write your base class and put abstract=True
in the Meta class. This model will then not be used to create any database table. Instead, when it is used as a base class for other models, its fields will be added to those of the child class. It is an error to have fields in the abstract base class with the same name as those in the child (and Django will raise an exception).
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
The Student
model will have three fields: name
, age
and home_group
. The CommonInfo model cannot be used as a normal Django model, since it is an abstract base class. It does not generate a database table or have a manager, and cannot be instantiated or saved directly.
For many uses, this type of model inheritance will be exactly what you want. It provides a way to factor out common information at the Python level, while still only creating one database table per child model at the database level.
2)
If you’re subclassing an existing model (perhaps something from another application entirely) and want each model to have its own database table, Multi-table inheritance is the way to go.
from django.db import models
class CommonInfo(models.Model):
# ...
class Meta:
abstract = True
ordering = ['name']
class Student(CommonInfo):
# ...
class Meta(CommonInfo.Meta):
db_table = 'student_info'
3)
Finally, if you only want to modify the Python-level behavior of a model, without changing the models fields in any way, you can use Proxy models.
from django.db import models
class Base(models.Model):
m2m = models.ManyToManyField(
OtherModel,
related_name="%(app_label)s_%(class)s_related",
related_query_name="%(app_label)s_%(class)ss",
)
class Meta:
abstract = True
class ChildA(Base):
pass
class ChildB(Base):
pass
Along with another app rare/models.py:
from common.models import Base
class ChildB(Base):
pass
For more information you may want to continue reading the documentation here.
There is a well maintenanced project, called django-mptt, that implementing Modified Preorder Tree Traversal with your Django Models and working with trees of Model instances.
0đź‘Ť
If i understand you right, you have two class hierarchies. You can use Bridge pattern to deal with it. Your custom hierarchy can be thought of as the abstraction and Django part as the implementation. The bridge pattern can also be thought of as two layers of abstraction.
The bridge pattern is a design pattern used in software engineering
that is meant to “decouple an abstraction from its implementation so
that the two can vary independently”, introduced by the Gang of Four
(GoF). The bridge uses encapsulation, aggregation, and can use
inheritance to separate responsibilities into different classes.
https://en.wikipedia.org/wiki/Bridge_pattern