MixAd问题为ModelAdmin

时间:2011-05-20 10:11:08

标签: django django-admin

我正在覆盖ModelAdmin方法:

def response_change(self, request, obj):
    # alter redirect location if 'source' is found in GET
    response = super(JobOptions, self).response_change(request, obj)
    source = request.GET.get('source', None)
    if source:
        response['location'] = source
    return response

而不是在每个模型上重复这个,我想把它变成混合物。

如果我这样做:

def RedirectMixin(admin.ModelAdmin)

然后:

def MyModel(admin.ModelAdmin, RedirectMixin)

然后我收到MRO错误。

但是,如果RedirectMixin没有从admin.ModelAdmin继承,则不会调用该方法。

另一个问题是如何推广super()调用,因此它没有硬编码的超类。

1 个答案:

答案 0 :(得分:11)

首先,我在你的例子中假设你的意思是class而不是def

无论如何,使用Mixin的正确方法是首先在要继承的类列表中使用它。所以:

class RedirectMixin(object):

class MyModelAdmin(RedirectMixin, admin.ModelAdmin):

这是因为Python按照声明的顺序浏览所有父类以查找方法,并调用它找到的第一个方法。

至于super,这根本不应该提到超类 - 这就是它的全部意义。它应该引用当前的类:

return super(MyModelAdmin, self).__init__(self, *args, **kwargs)

或其他什么。

评论后修改是的,mixin应该在super调用中引用自己的类。请考虑以下事项:

In [1]: class BaseClass(object):
   ...:     def my_function(self):
   ...:         print 'base my_function'
   ...:     

In [2]: class Mixin(object):
   ...:     def my_function(self):
   ...:         print 'mixin my_function'
   ...:         super(Mixin, self).my_function()
   ...: 

In [3]: class MyDerivedClass(Mixin, BaseClass):
   ...:     pass
   ...: 

现在,如果你实例化子类并调用它的my_function方法,那么即使Mixin不从BaseClass继承,MRO也会按预期发生:

In [4]: m=MyDerivedClass()

In [5]: m.my_function()
mixin my_function
base my_function

如果你没有让Mixin成为object的后代,那么你提到的错误就会出现 - 如果你不这样做,那就是一个老式的类,它不支持使用super。