Jor*_*ata 17 python django listview multiple-inheritance django-generic-views
我创建了一个子类ListView和两个已实现get_context_data函数的自定义mixin的类.我想在子类上覆盖此函数:
from django.views.generic import ListView
class ListSortedMixin(object):
def get_context_data(self, **kwargs):
print 'ListSortedMixin'
return kwargs
class ListPaginatedMixin(object):
def get_context_data(self, **kwargs):
print 'ListPaginatedMixin'
return kwargs
class MyListView(ListSortedMixin, ListPaginatedMixin, ListView):
def get_context_data(self, **context):
super(ListSortedMixin,self).get_context_data(**context)
super(ListPaginatedMixin,self).get_context_data(**context)
return context
Run Code Online (Sandbox Code Playgroud)
当我执行MyListView它时只打印"ListSortedMixin".出于某种原因,python正在执行ListSortedMixin.get_context_data而不是代替MyListView.get_context_data.为什么?
如果我将继承顺序更改为ListPaginatedMixin, ListSortedMixin, ListView,ListPaginatedMixin.get_context_data则执行.
我该如何覆盖该get_context_data功能?
Dan*_*alm 20
这是一个老问题,但我认为答案是不正确的.您的代码中存在错误.它应该是:
class MyListView(ListSortedMixin, ListPaginatedMixin, ListView):
def get_context_data(self, **context):
super(MyListView,self).get_context_data(**context)
return context
Run Code Online (Sandbox Code Playgroud)
在其中的顺序get_context_data将被称为如下如在声明中指定的相同顺序MyListView.注意super的参数是,MyListView而不是超类.
更新:
我错过了你的mixins不叫超级.他们应该.是的,即使它们继承自object,因为super调用MRO中的下一个方法,不一定是它所在的类的父类.
from django.views.generic import ListView
class ListSortedMixin(object):
def get_context_data(self, **kwargs):
print 'ListSortedMixin'
return super(ListSortedMixin,self).get_context_data(**context)
class ListPaginatedMixin(object):
def get_context_data(self, **kwargs):
print 'ListPaginatedMixin'
return super(ListPaginatedMixin,self).get_context_data(**context)
class MyListView(ListSortedMixin, ListPaginatedMixin, ListView):
def get_context_data(self, **context):
return super(MyListView,self).get_context_data(**context)
Run Code Online (Sandbox Code Playgroud)
对于MyListViewMRO来说:
逐个调用它们可能有效,但不是如何使用它.
更新2
复制并粘贴示例以证明我的观点.
class Parent(object):
def get_context_data(self, **kwargs):
print 'Parent'
class ListSortedMixin(object):
def get_context_data(self, **kwargs):
print 'ListSortedMixin'
return super(ListSortedMixin,self).get_context_data(**kwargs)
class ListPaginatedMixin(object):
def get_context_data(self, **kwargs):
print 'ListPaginatedMixin'
return super(ListPaginatedMixin,self).get_context_data(**kwargs)
class MyListView(ListSortedMixin, ListPaginatedMixin, Parent):
def get_context_data(self, **kwargs):
return super(MyListView,self).get_context_data(**kwargs)
m = MyListView()
m.get_context_data(l='l')
Run Code Online (Sandbox Code Playgroud)
Mar*_*mro 10
如果你要做的是按固定顺序调用覆盖的方法.使用以下语法:
class MyListView(ListSortedMixin, ListPaginatedMixin, ListView):
def get_context_data(self, **context):
ListSortedMixin.get_context_data(self, **context)
ListPaginatedMixin.get_context_data(self, **context)
return context
Run Code Online (Sandbox Code Playgroud)
在这种情况下,超级不起作用.请参阅手册super(type[, object]):
返回将方法调用委托给父类或兄弟类类型的代理对象.这对于访问已在类中重写的继承方法很有用.搜索顺序与getattr()使用的搜索顺序相同,只是跳过了类型本身.
super有两个典型的用例.在具有单继承的类层次结构中,super可用于引用父类而不显式命名它们,从而使代码更易于维护.这种用法与其他编程语言中super的使用密切相关.
第二个用例是在动态执行环境中支持协作多重继承.此用例是Python独有的,在静态编译语言或仅支持单继承的语言中找不到.这使得实现"菱形图"成为可能,其中多个基类实现相同的方法.好的设计要求此方法在每种情况下都具有相同的调用签名(因为调用的顺序是在运行时确定的,因为该顺序适应类层次结构中的更改,并且因为该顺序可以包括在运行时之前未知的兄弟类).
所以super的参数是你想要获得父类或兄弟类代理的类.super(ListSortedMixin,self).get_context_data(**context)不一定会叫get_context_data的ListSortedMixin.这取决于您可以使用的方法分辨率顺序(MRO)print MyListView.__mro__
所以super()会打电话给get_context_data父母或兄弟姐妹.执行顺序适应类层次结构中的更改,因为该顺序可以包括运行时之前未知的兄弟类.
| 归档时间: |
|
| 查看次数: |
9925 次 |
| 最近记录: |