On 3 November 2010 22:17, Marc Aymerich <[email protected]> wrote:
> Hi,
> I have 2 abstract classes with an overrided save function, class BaseA and
> class BaseB. BaseA trigger the models.Model save function, the other
> doesn't.
> class BaseA(models.Model):
> class Meta:
> abstract = True
> def save(self, *args, **kwargs):
> super(BaseA, self).save(*args, **kwargs)
>
> class BaseB(models.Model):
> class Meta:
> abstract = True
>
> def save(self, *args, **kwargs):
> pass
> Now I define a class that inherits from both of these classes:
> class test1(BaseA, BaseB):
> integer = models.IntegerField()
> and when I save a test1 object it is not saved into the database. The reason
> is that BaseB class doesn't call super save function. But actually I don't
> see why this fact entails the object isn't saved, because models.Model
> function is called through BaseA. What is the reason of this behavior?
Model.save is never called. The super() in Python doesn't work like
you think. It needs to be a little bit smarter to make multiple
inheritance work, so the anwser is a bit complicated.
Here super() looks at the runtime type of `self`, searches for class
BaseA in it's Method Resolution Order (MRO) and then takes the next
class in that order. So in your code
class test1(BaseA, BaseB):
integer = models.IntegerField()
`test1` will have a MRO of [test1, BaseA, BaseB, Model, ... some
irrelevant django stuff ... , object] (you can also check that with
test1.__mro__). Not going into details, immediate base classes are
always most important with the one on the left side being most
important of them. So, the super().save() in BaseA will call the save
method in BaseB which in turn will do nothing and Model.save() will
never get called.
For more information on MRO you can see the official documentation[1]
or just google for "Python MRO".
> What can I do in order to save an object into the db when I inherit from
> multiple
> class and one of them doesn't call the super save function?
Fix the class that doesn't call super(). The class should either call
super() or not provide the method at all. Otherwise it won't play well
with inheritance.
You can try changing BaseA.save to call Model.save instead of the
super call, but then BaseA.save will never call BaseB.save if you ever
decide to put any code there.
Sorry, if it's not very clear.
[1]: http://www.python.org/download/releases/2.3/mro/
--
Łukasz Rekucki
--
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-users?hl=en.