我刚刚开始super思考 Django 中基于视图的类是什么以及它是如何实现的。我试图了解 super 在以下代码中的工作方式。有人可以尝试为我逐个分解吗?
from django.views.generic.detail import DetailView
from apps.app_name.models import Article
class ArticleDetailView(DetailView):
model = Article
template_name = 'article/show.html'
def get_context_data(self, **kwargs):
context = super(ArticleDetailView, self).get_context_data(**kwargs)
return context
Run Code Online (Sandbox Code Playgroud)
该super方法将访问当前类并调用特定方法,在本例中:
super(ArticleDetailView, self) # Access to the current class
Run Code Online (Sandbox Code Playgroud)
并执行具体方法:
.get_context_data(**kwargs)
Run Code Online (Sandbox Code Playgroud)
.get_context_data()类中的方法,View返回context传递给模板(.html文件)的内容。在本例中,您使用的是DetailView,因此您有一些预定义的上下文,例如:object或article。
如果您只是覆盖.get_context_data()而不调用.super(),如下所示:
def get_context_data(self, **kwargs):
my_context = {...}
return my_context
Run Code Online (Sandbox Code Playgroud)
您将丢失上下文中的预定义变量DetailView。但是如果你想向当前的DetailView上下文添加一些新的变量(值),你需要原始的上下文,这就是super(ArticleDetailView, self).get_context_data(**kwargs)给你的。所以你会这样使用它:
def get_context_data(self, **kwargs):
context = super(ArticleDetailView, self).get_context_data(**kwargs)
context.update({'my_key': 'my_value'})
return context
Run Code Online (Sandbox Code Playgroud)
现在,您将能够在模板中使用您自己的值,而不会丢失默认的DetailView上下文值。
正如目前所写,该方法绝对没有任何作用,可以删除。
上下文数据方法直接委托给继承链中的下一个类。在这种情况下,这意味着使用超类DetailView.get_context_data。
但是,如果该方法不存在于 上,无论如何都会发生这种情况ArticleDetailView。所以这样写是没有意义的,明确地传递给超类。
所以,代码很奇怪 - 这能回答你的问题吗?
例如,如果你真的想在子类中做一些不同的事情,那么实现这个方法是有意义的。例如:
def get_context_data(self, **kwargs):
context = super(ArticleDetailView, self).get_context_data(**kwargs)
context['new_key'] = 'some injected context from ArticleDetailView'
return context
Run Code Online (Sandbox Code Playgroud)
然后我们使用来自 的上下文数据DetailView,并在 中添加额外的上下文ArticleDetailView。
使用super(ArticleDetailView, self).get_context_data而不是简单地DetailView.get_context_data直接使用的原因很复杂,并且与方法解析顺序(MRO)有关。Raymond Hettinger 在这里进行了一些详细的解释。
注意:在 python 3 中 super 的实现被清理了一点,你不再需要super(ArticleDetailView, self)你可以使用,super()谢天谢地。