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.

Asked By: Olivier Pons

||

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

Answered By: Geo Jacob

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.

Answered By: Rahul Gupta

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
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.