Django: how to create custom "base" model
Question:
In almost all my tables (= classes of models.Model
) I have three DateTimeField
:
- creation
- validity start
- validity end
Is there a way to have a “base” model class where I declare those fields, and make all my other model extend this one? I couldn’t find a valuable answer on the Web.
Answers:
class Basetable(models.Model):
created_on = models.DateTimeField(auto_now_add=True)
modified_on = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='%(class)s_createdby')
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='%(class)s_modifiedby', null=True, blank=True)
class Meta:
abstract = True
This way you can define your model and extend Basetable to other model class
You need to create an abstract base class having these common fields and then inherit this base class in your models.
Step-1: Create a new Abstract Base Class
We first create an abstract base class called BaseModel
. This BaseModel
class contains the 3 model fields creation_date
, valididity_start_date
and validity_end_date
which are common in almost every model of yours.
In the inner Meta
class, we set abstract=True
. 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.
class BaseModel(models.Model): # base class should subclass 'django.db.models.Model'
creation_date = models.DateTimeField(..) # define the common field1
validity_start_date = models.DateTimeField(..) # define the common field2
validity_end_date = models.DateTimeField(..) # define the common field3
class Meta:
abstract=True # Set this model as Abstract
Step-2: Inherit this Base class in your models
After creating the abstract base class BaseModel
, we need to inherit this class in our models. This can be done using normal inheritance as done in Python.
class MyModel1(BaseModel): # inherit the base model class
# define other non-common fields here
...
class MyModel2(BaseModel): # inherit the base model class
# define other non-common fields here
...
Here, MyModel1
and MyModel2
classes contain the 3 fields creation_date
, valididity_start_date
and validity_end_date
from the base class BaseModel
apart from the other model fields defined in it.
This way you can define your model and extend the Base model to other model classes. I hope this will help you to make a clean and reusable architecture for your Django-based project.
class ActiveManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(active=True).order_by('-
created_at')
class InactiveManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(active=False)
class BaseModel(models.Model):
"""
Used in all the models as base
"""
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True,
blank=True,
help_text='If this object is active')
active_objects = ActiveManager()
inactive_objects = InactiveManager()
objects = models.Manager()
created_by = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,related_name='%.
(class)s_created_by', null=True, blank=True,)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='%(class)s_updated_by',
on_delete=models.SET_NULL,
null=True, blank=True,)
class Meta:
abstract = True
In almost all my tables (= classes of models.Model
) I have three DateTimeField
:
- creation
- validity start
- validity end
Is there a way to have a “base” model class where I declare those fields, and make all my other model extend this one? I couldn’t find a valuable answer on the Web.
class Basetable(models.Model):
created_on = models.DateTimeField(auto_now_add=True)
modified_on = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='%(class)s_createdby')
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='%(class)s_modifiedby', null=True, blank=True)
class Meta:
abstract = True
This way you can define your model and extend Basetable to other model class
You need to create an abstract base class having these common fields and then inherit this base class in your models.
Step-1: Create a new Abstract Base Class
We first create an abstract base class called BaseModel
. This BaseModel
class contains the 3 model fields creation_date
, valididity_start_date
and validity_end_date
which are common in almost every model of yours.
In the inner Meta
class, we set abstract=True
. 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.
class BaseModel(models.Model): # base class should subclass 'django.db.models.Model'
creation_date = models.DateTimeField(..) # define the common field1
validity_start_date = models.DateTimeField(..) # define the common field2
validity_end_date = models.DateTimeField(..) # define the common field3
class Meta:
abstract=True # Set this model as Abstract
Step-2: Inherit this Base class in your models
After creating the abstract base class BaseModel
, we need to inherit this class in our models. This can be done using normal inheritance as done in Python.
class MyModel1(BaseModel): # inherit the base model class
# define other non-common fields here
...
class MyModel2(BaseModel): # inherit the base model class
# define other non-common fields here
...
Here, MyModel1
and MyModel2
classes contain the 3 fields creation_date
, valididity_start_date
and validity_end_date
from the base class BaseModel
apart from the other model fields defined in it.
This way you can define your model and extend the Base model to other model classes. I hope this will help you to make a clean and reusable architecture for your Django-based project.
class ActiveManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(active=True).order_by('-
created_at')
class InactiveManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(active=False)
class BaseModel(models.Model):
"""
Used in all the models as base
"""
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True,
blank=True,
help_text='If this object is active')
active_objects = ActiveManager()
inactive_objects = InactiveManager()
objects = models.Manager()
created_by = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,related_name='%.
(class)s_created_by', null=True, blank=True,)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='%(class)s_updated_by',
on_delete=models.SET_NULL,
null=True, blank=True,)
class Meta:
abstract = True