[Django]-Adding to the "constructor" of a django model

25👍

Overriding __init__ might work, but it’s bad idea and it’s not the Django way.

The proper way of doing it in Django is using signals.

The ones that are of interest to you in this case are pre_init and post_init.

django.db.models.signals.pre_init

Whenever you instantiate a Django
model, this signal is sent at the beginning of the model’s __init__()
method.

django.db.models.signals.post_init

Like pre_init, but this one is sent
when the __init__(): method finishes

So your code should be something like

from django.db import models
from django.db.models.signals import post_init

class MyModel(models.Model):
  # normal model definition...

def extraInitForMyModel(**kwargs):
   instance = kwargs.get('instance')
   do_whatever_you_need_with(instance)

post_init.connect(extraInitForMyModel, MyModel)

You can as well connect signals to Django’s predefined models.

👤vartec

7👍

While I agree that there often is a better approach than overriding the __init__ for what you want to do, it is possible and there might be cases where it could be useful.

Here is an example on how to correctly override the __init__ method of a model without interfering with Django’s internal logic:

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # add your own logic

5👍

The two suggested methods in the docs rely on the instance being created in an arbitrary way:

  1. Add a classmethod on the model class:

    from django.db import models
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
    
        @classmethod
        def create(cls, title):
            book = cls(title=title)
            # do something with the book
            return book
    
    book = Book.create("Pride and Prejudice")
    
  2. Add a method on a custom manager:

    class BookManager(models.Manager):
        def create_book(self, title):
            book = self.create(title=title)
            # do something with the book
            return book
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
    
        objects = BookManager()
    
    book = Book.objects.create_book("Pride and Prejudice")
    

If that is your case, I would go that way. If not, I would stick to @vartec’s answer.

Leave a comment