Django 如何扩展通用 View 类

标签 django django-views

我注意到我正在为网站上的许多 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/

相关文章:

django 为在外键字段模型中创建的新实例自动创建中间模型实例

python - 获取 ValueError : invalid literal for int() with base 10: '' error and don't know why

python - 如何验证用户 "owns"是否是模型实例

django - 在 Django 模板中访问查询集的 'values_list'

python - 获取模板中所有自定义用户的列表(Django)

python - 使用可重用方法和错误处理设置基于类的 View 架构

python - 如何在 Django 用户模型中添加新字段

python - 如何访问 Amazon EC2 实例上的 Django 管理站点?

python - 如何根据从另一个表数据获取的id来获取表数据? Django

python - 如何在 Django 中更新 ImageField?