Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initiate post save on Django abstract parent model, when child model saved

i have this models:

from django.db.models import Model

class SearchModel(Model):  
    class Meta:
        abstract = True

class Book(SearchModel):

    book_id = django_models.BigIntegerField(null=True, blank=True)

    class Meta:
        db_table = 'book'

I need that on book.save() a SearchModel function should be called (without any code changes on Book/not creating post save signal on Book)

My motivation is that every model inherit from SearchModel, will have some post_save handler (without writing extra code - only inherit Signal)

Is it possible?

like image 309
Eyal Ch Avatar asked Jan 06 '16 14:01

Eyal Ch


People also ask

What is the purpose of __ Str__ method in Django?

str function in a django model returns a string that is exactly rendered as the display name of instances for that model. # Create your models here. This will display the objects as something always in the admin interface.

Why do we use abstract models in Django?

Abstract Base Class 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.

What is abstract true in Django models?

An abstract model is a base class in which you define fields you want to include in all child models. Django doesn't create any database table for abstract models. A database table is created for each child model, including the fields inherited from the abstract class and the ones defined in the child model.


2 Answers

That's quite simple: don't provide any specific "sender" when connecting your post_save handler, then in the handler check whether sender is a subclass of SearchModel, ie:

from django.db.signals import post_save
from django.dispatch import receiver
from django.db.models import Model

class SearchModel(Model):  
    class Meta:
        abstract = True

    def on_post_save(self):
        print "%s.on_post_save()" % self

# NB `SearchModel` already inherits from `Model` 
class Book(SearchModel):
    book_id = django_models.BigIntegerField(null=True, blank=True)

    class Meta:
        db_table = 'book'


@receiver(post_save)
def search_on_post_save(sender, instance, **kwargs):
    if issubclass(sender, SearchModel):
         instance.on_post_save()

Then you can provide a default implementation in SearchModel and override it if needed in subclasses.

like image 183
bruno desthuilliers Avatar answered Nov 15 '22 00:11

bruno desthuilliers


In your signals.py

from django.db.signals import post_save

def search_on_post_save(sender, instance, **kwargs):
    pass

for subclass in SearchModel.__subclasses__():
    post_save.connect(search_on_post_save, subclass)
like image 39
Daniil Mashkin Avatar answered Nov 14 '22 23:11

Daniil Mashkin