Does it make sense to override the save
method in a mixin?
In my project I have, for good reasons, to override the save
method in several models.
At first, I have to create a custom model class which inherits from models.Model
.
However, semantically, what I am doing is giving a role to a class (rather than defining an object in its own right), that's why I think it's better to write a mixin.
An other reason is because we may use multiple inheritance in near future.
On the over hand, this line in overridden save method :
super(MyMixin, self).save(*args, **kwargs)
does not make sense as it can only be used with a django.db.models.Model class.
class MyMixin(object):
def save(self, *args, **kwargs):
...
super(MyMixin, self).save(*args, **kwargs)
...
Which is the technically better choice (Mixin or custom model)?
The way the mro (method resolution order) works, both methods are perfectly valid. The abstract model case is quite simple: you have a single inheritance chain, and each call to super is called on the next class up in the chain. So if you have:
class MyBaseModel(models.Model):
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
class MyModel(MyBaseModel):
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
The call in MyModel
will propogate to MyBaseModel
, and the call in MyBaseModel
will propogate to models.Model
.
With multiple inheritance, the inheritance chain is slightly different. The first class upwards in the inheritance chain is the first base class defined. So if you have class MyModel(MyMixin, models.Model)
, MyMixin
will be the first class upwards. Next, when super()
is called in MyMixin
(with a MyModel
instance), it will look for siblings of the MyMixin
class. That means that the next method to be called is the save
method on models.Model
.
Considering this, it is perfectly fine to use a mixin to override the save methods. In both cases, the MyModel
save method will be called first, then the mixin/abstract model's save method, and finally the models.Model
save method.
Note:
This is a simplified explanation of the method resolution order that works in this specific case. The actual algorithm for determining the order is the C3 linearization algorithm. A complete explanation can be found here.