Model Inheritance
Don’t Build Custom User Models Like This!
The following examples are a convenient way to show you how multi-table inheritance and abstract base classes work without messing up the models in your database.
This is not how you would go about creating a custom user model as it’s not connected to Django’s authentication system. Also, Django’s User
class includes first_name
, last_name
, email
and date_joined
fields, so you need not create them yourself.
I will show you how to extend Django’s User
class in Chapter 14.
Models are Python classes, so inheritance works the same way as normal Python class inheritance. The two most common forms of model inheritance in Django are:
- Multi-table inheritance, where each model has its own database table; and
- Abstract base classes, where the parent model holds information common to all its child classes but doesn’t have a database table.
You can also create proxy models to modify the Python-level behavior of a model without modifying the underlying model fields, however, we won’t be covering them here. See the Django documentation for more information on proxy models.
Multi-table Inheritance
With multi-table inheritance, the parent class is a normal model, and the child inherits the parent by declaring the parent class in the child class declaration. For example:
# Example for illustration - don't add this to your code!
class MyClubUser(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField('User Email')
def __str__(self):
return self.first_name + " " + self.last_name
class Subscriber(MyClubUser):
date_joined = models.DateTimeField()
The parent model in the example is the MyClubUser
model from our events
app. The Subscriber
model inherits from MyClubUser
and adds an additional field (date_joined
). As they are both standard Django model classes, a database table is created for each model. I’ve created these models in my database, so you can see the tables Django creates (Figure 9-1).
Figure 9-1: Database tables are created for both the parent and the child model. You will only see these tables if you run the example code.
Abstract Base Classes
Abstract base classes are handy when you want to put common information into other models without having to create a database table for the base class.
You create an abstract base class by adding the abstract = True
class Meta
option (line 7 in this illustrative example):
# Example for illustration - don't add this to your code!
1 class UserBase(models.Model):
2 first_name = models.CharField(max_length=30)
3 last_name = models.CharField(max_length=30)
4 email = models.EmailField('User Email')
5
6 class Meta:
7 abstract = True
8 ordering = ['last_name']
9
10
11 class MyClubUser(UserBase):
12 def __str__(self):
13 return self.first_name + " " + self.last_name
14
15
16 class Subscriber(UserBase):
17 date_joined = models.DateTimeField()
Abstract base classes are also useful for declaring class Meta
options that are inherited by all child models (line 8).
As the MyClubUser
model from our events
app now inherits the first name, last name and email fields from UserBase
, it only needs to declare the __str__()
function to behave the same way as the original MyClubUser
model we created earlier.
This example is very similar to the example for multi-table inheritance in the previous section, and if you saved and migrated these models, you would get the same result as Figure 9-1—Django would create the events_myclubuser
and events_subscriber
tables in your database, but, because UserBase
is an abstract model, it won’t be added to the database as a table.