mehmet
mehmet

Reputation: 8174

super() method resolution in python

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

Answers (1)

Daniel Roseman
Daniel Roseman

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

Related Questions