写在前面
- 在上一篇 mixin类实现用户登录装饰器中遗留了一个问题,LoginRequiredMixin中的super()中的as_view方法,究竟来自哪里?
参考博客
回到 LoginRequiredMixin 例子中来
涉及到的三个类
- LoginRequiredMixin(实现用户登录装饰器功能)
- View类(Django部分源码)
- UserInfoView类(继承 LoginRequiredMixin、View类)
from django.contrib.auth.decorators import login_required
# LoginRequiredMixin 类
class LoginRequiredMixin(object):
@classmethod
def as_view(cls, **initkwargs):
# 调用父类的as_view
view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
return login_required(view)
# View类
class View:
...
@classonlymethod
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key))
...
# UserInfoView类
class UserInfoView(LoginRequiredMixin, View):
'''用户中心-信息页'''
def get(self, request):
'''显示'''
# page = 'user'
return render(request, 'df_user/user_center_info.html', {'page': 'user'})
提出问题
从上面可以看出,我们的 LoginRequiredMixin 继承的是object,但是object并没有as_view()方法,那么 LoginRequiredMixin 究竟调用了谁的as_view 方法呢?
问题解释
在多继承的环境下,super() 有相对来说更加复杂的含义。它会查看你的继承链,使用一种叫做 Methods Resolution Order(方法解析顺序) 的方式,来决定调用最近的继承父类的方法。
LoginRequiredMixin.as_view()的调用行为:
-
UserInfoView.as_view() 方法被解析为 LoginRequiredMixin.as_view() 方法的调用。因为对于 UserInfoView 类来说,在继承链上的两个父类,LoginRequiredMixin 和 View 来说,LoginRequiredMixin是最近的,因此调用 LoginRequiredMixin 的 as_view 方法
-
LoginRequiredMixin.as_view() 方法调用了 super().as_view(),这一行代码按照刚才的解释,查看 UserInfoView 的继承链,是应该调用 View 类的 as_view() 方法的。这一步是相对来说比较难以理解的。
LoginRequiredMixin调用解释
-
当 LoginRequiredMixin.as_view() 中调用了 super().as_view() 的时候,它会 尝试去寻找属于当前类的继承链。
-
而这个当前类是什么类呢?不是 LoginRequiredMixin 类,而是 UserInfoView 类, UserInfoView 类的继承连是 LoginRequiredMixin 然后是 View 类的 as_view() 方法。
总结
-
简单记住:self.method() 将会先在当前类中查看 method() 方法,如果没有,就在继承链中进行查找,查找顺序就是你继承的顺序从左到右,直到 method() 方法被找到。
-
super().method() 与 self.method() 是差不多的,只是 super().method() 需要跳过当前类而已。
-
Mixin 类总是需要与其他类混合来加强其他类,可以大大简化和方便我们的代码的开发过程。
网友评论