Reputation: 8174
I am creating two custom widgets for django to use the chosen jQuery plugin, one for ForeignKey
model fields and the other ManyToManyField
. So, respectively, I override forms.Select
and forms.SelectMultiple
. I put the common functionality in a common parent class as:
class ChosenWidgetParent(object):
class Media:
css = {
'all': (
'sub/staticfull/css/plugins/chosen/chosen.css',
)
}
js = (
'sub/staticfull/js/jquery-2.1.1.js',
'sub/staticfull/js/plugins/chosen/chosen.jquery.js',
)
def render(self, name, value, attrs=None, **kwargs):
attrs['chosen'] = 'chosen'
rendered = super().render(name, value, attrs, **kwargs)
return rendered + mark_safe(u'''
<script>
$(document).ready(function () {
$('#id_%(name)s').chosen({
disable_search_threshold: 10,
})
})
</script>''' % {'name': name})
Note there is a call to super, which should refer to Select
's and SelectMultiple
's render methods respectively.
And then, I define my classes:
class ChosenWidgetMultiple(widgets.SelectMultiple, ChosenWidgetParent):
pass
class ChosenWidget(widgets.Select, ChosenWidgetParent):
pass
This does not work unfortunately, but when I swap the parent classes, it works.
class ChosenWidgetMultiple(ChosenWidgetParent, widgets.SelectMultiple):
pass
class ChosenWidget(ChosenWidgetParent, widgets.Select):
pass
Can someone explain me why?
Upvotes: 0
Views: 80
Reputation: 600059
Because that's the way method resolution works. Python will go through the classes in the order they are declared and call the first method it finds. When you declare the original widget first, Python will find its render method and call it; it will never proceed to your implementation. But when you put yours first, Python will call that, and then when it gets to super() will call the original.
Upvotes: 1