Say, I have the following mixins that overlaps with each other by touching dispatch()
:
class FooMixin(object):
def dispatch(self, *args, **kwargs):
# perform check A
...
return super(FooMixin, self).dispatch(*args, **kwargs)
class BarMixin(object):
def dispatch(self, *args, **kwargs):
# perform check B
...
return super(FooMixin, self).dispatch(*args, **kwargs)
If I want my view to go through the order, check A -> check B, should my code be MyView(FooMixin, BarMixin, View)
or MyView(BarMixin, FooMixin, View)
?
And why do we always put View
or its subclasses after mixins? (I have noticed this from reading the source code of the django generic views, but I don't know the rationale behind it, if any)
Mixins are a language concept that allows a programmer to inject some code into a class. Mixin programming is a style of software development, in which units of functionality are created in a class and then mixed in with other classes. A mixin class acts as the parent class, containing the desired functionality.
It's perfectly valid for a mixin to inherit from another mixin - in fact, this is how most of Django's more advanced mixins are made. However, the idea of mixins is that they are reusable parts that, together with other classes, build a complete, usable class.
Mixins are sometimes described as being "included" rather than "inherited". In short, the key difference from an inheritance is that mix-ins does NOT need to have a "is-a" relationship like in inheritance. From the implementation point of view, you can think it as an interface with implementations.
Mixins are an alternative class design pattern that avoids both single-inheritance class fragmentation and multiple-inheritance diamond dependencies. A mixin is a class that defines and implements a single, well-defined feature. Subclasses that inherit from the mixin inherit this feature—and nothing else.
The MRO is basically depth-first, left-to-right. See Method Resolution Order (MRO) in new style Python classes for some more info.
You can look at the __mro__
attribute of the class to check, but FooMixin
should be first if you want to do "check A" first.
class UltimateBase(object): def dispatch(self, *args, **kwargs): print 'base dispatch' class FooMixin(object): def dispatch(self, *args, **kwargs): print 'perform check A' return super(FooMixin, self).dispatch(*args, **kwargs) class BarMixin(object): def dispatch(self, *args, **kwargs): print 'perform check B' return super(BarMixin, self).dispatch(*args, **kwargs) class FooBar(FooMixin, BarMixin, UltimateBase): pass FooBar().dispatch()
Prints:
perform check A perform check B base dispatch
View
has to be last so that it "catches" any attribute lookups that weren't on any mixins, without hiding any methods on those mixins. I'm not sure I understand that part of your question -- what it "why is it added at all" or "why is it added last"?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With