我注意到我正在为网站上的许多 View 设置网站范围的上下文变量和请求变量。这种情况自然需要继承。如果我所有基于 View 类的 View 都继承自 SiteView 而不是通用 View,那么我可以将所有共性分解到 SiteView 子类中。然后我可以从 SiteView 继承我的所有 View 。但是,我无法让它发挥作用。这是我的代码:
from django.contrib.auth.decorators import login_required
from django.views.generic import View
from django.utils.decorators import method_decorator
class SiteView(View):
''' Extends the generic django-supplied View class '''
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(SiteView, self).dispatch(*args, **kwargs)
def get(self, *args, **kwargs):
''' Adds the variables required in the get request '''
context = super(SiteView, self).get(*args, **kwargs)
context['common_var'] = 'some common value'
context['user'] = request.user
return self.render_to_response(context)
这会引发以下类型错误:
dispatch() missing 1 required positional argument: 'request'
如有任何帮助,我们将不胜感激
编辑:尽管标记了正确答案,但代码还存在其他问题。特别是,SiteView 的 get 方法不应包含以下行:
context = super(SiteView, self).get(*args, **kwargs)
这是因为 View 类没有任何 get 方法。
最佳答案
您忘记将请求传递给 super().dispatch(..)
调用:
class SiteView(View):
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(SiteView, self).dispatch(<b>request,</b> *args, **kwargs)
或者您可以省略 dispatch
参数中的 request
,从而通过 *args
和 **kwargs 传递它
:
class SiteView(View):
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(SiteView, self).dispatch(*args, **kwargs)
然而,传递函数的名称可能更优雅,例如:
@method_decorator(login_required<b>, name='dispatch'</b>)
class SiteView(View):
# ...
编辑:请注意,View
没有 get(..)
、post(..)
等方法。 dispatch(..)
方法将查找此类方法是否存在,如果存在则重定向到它。如果该方法不存在,则会返回“405 Method Not allowed”响应。
您的 get(..)
函数的实现如下:
@method_decorator(login_required, name='dispatch')
class SiteView(View):
''' Extends the generic django-supplied View class '''
def <b>render_to_response</b>(self, context):
# ...
def get(self, request, *args, **kwargs):
context = {
'common_var': 'some common value',
'user': request.user
}
return self.render_to_response(context)
实现“mixin”(可能使用 LoginRequiredMixin
mixin [Django-doc] 的子类)可能更有意义。
例如:
class SiteViewMixin(LoginRequiredMixin):
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context.update(common_var='some common value', user=self.request.user)
return context
然后在另一个 View 中使用 mixin,例如:
class SomeView(<b>SiteViewMixin</b>, TemplateView):
# ...
关于Django 如何扩展通用 View 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57401966/