A model template in your Django app
Posted on Tue 10 March 2020 in Python • 3 min read
Table of Contents
This is something I recently stumbled over. A way to reduce the DRY (Don't repeat yourself) in the models of your Django app.
Most of the times I find that I have the two same fields in my Django models. Added and edited. Both are DateTimeFields. Added gets the date when the row in the database is created, the other will be updated with the current time when the row is updated.
In this article I'll show you how you can make a template model with these fields included, and inherit them from this template model in your other models. That way you don't have to write, or copy/paste those fields for every new model you create.
Creating an abstract base class in Django
What is an Abstract base class in Django? If you check the documentation it reads:
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.
The added and edited fields can be put in an abstract base class, which will not be put in any database table. So when inheriting from this abstract model in the other models, those fields will be added to the table of those models.
The abstract class in this scenario can look like this:
# models.py
from django.db import models
class TimeStampedModel(models.Model):
added = models.DateTimeField(auto_now_add=True)
edited = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
It is a common Django model that inherits from django.db.models.Model
, but in its Meta class we put abstract = True
Use the abstract class in a Django model class
To make use of this "model template" in one of our models, all we have to do is inherit from the abstract class. For example, in one of my previous articles I had a model for Beer, which included an added and edited field.
# models.py
from django.db import models
class Beer(models.Model):
name = models.CharField(max_length=100)
tagline = models.CharField(max_length=200)
first_brewed = models.CharField(max_length=20)
description = models.TextField()
added = models.DateTimeField(auto_now_add=True)
edited = models.DateTimeField(auto_now=True)
def __str__(self):
return f'Beer: {self.name}'
Instead of writing the model as I did there, it can be rewritten like this:
# models.py
from django.db import models
class TimeStampedModel(models.Model):
added = models.DateTimeField(auto_now_add=True)
edited = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Beer(TimeStampedModel):
name = models.CharField(max_length=100)
tagline = models.CharField(max_length=200)
first_brewed = models.CharField(max_length=20)
description = models.TextField()
# added and edited is removed
def __str__(self):
return f'Beer: {self.name}'
The Beer class now inherits from the TimeStampedModel
so there is no need for the added and edited field. It will get those from the parent class. Having multiple models in an app where those two fields are needed, this saves some repeated code.
Conclusion
In this article I have showed how you can make a model template in your Django app for fields that are common in most of your models in the app. This was just a small toy demo of how it works. Have a look in the documentation (linked below) for further capabilities with these abstract classes
Resources
Let me know on Twitter if I can improve this article, or if you have other resources to help out with understanding this topic.