在基于 class 的视图中设置基于条件的重定向 (Django)

Setting a condition based redirect in a class based view (Django)

我(初学者)正在创建一个简单的博客应用程序。我创建了一个基于 class 的视图来创建一个博客 post,它有一个单独的 URL。如果用户未登录,我希望它重定向到登录页面 (url name = 'login')。在基于函数的视图中,我所要做的就是:

def postCreateView(request):
if not request.user.is_authenticated:
    return redirect('login')

我不知道如何在基于 class 的视图(继承自通用 CreateView)中执行此操作。我尝试像这样修改 init() 方法:

def redirectLogin(self):
     return redirect('login')

 def __init__(self, *args, **kwargs):
     if(not self.request.user.is_authenticated):
         redirectLogin()
     super().__init__()

(我将 class 命名为 PostCreateView)但是在调试时异常值是 'PostCreateView' object has no attribute 'request'。我需要正确的方式(如果存在 Django 约定方式)在基于 class 的视图中设置基于条件的重定向。

我也很困惑为什么它说视图没有属性 'request'。每个视图都有请求。我对此很确定,因为我覆盖了 form_valid() 方法以将 post 的作者设置为当前登录的用户,如下所示:

def form_valid(self, form):
    form.instance.author = self.request.user
    return super().form_valid()

当我登录并创建 post.

时,它 运行 非常好

提前致谢。

Every view has request. I'm sure about it because I overrode the form_valid()

不,因为那是构造函数。你在构造视图对象时立即进行检查,此时 requestargskwargs 尚未设置 。事实上,这些是在对象构造之后设置的。您可以在 view function [GitHub]:

的源代码中看到这一点
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.<b>setup(</b>request, *args, **kwargs<b>)</b>
            if not hasattr(self, 'request'):
                raise AttributeError(
                    "%s instance has no 'request' attribute. Did you override "
                    "setup() and forget to call super()?" % cls.__name__
                )
            return self.dispatch(request, *args, **kwargs)

setup function [GitHub] 设置 .request.args.kwargs

    def setup(self, request, *args, **kwargs):
        """Initialize attributes shared by all view methods."""
        <b>self.request = request</b>
        self.args = args
        self.kwargs = kwargs

即使有一个请求对象,也不能解决问题,因为在 __init__ 中返回一个 redirect 不是底层视图机制预期的,它会因此,很可能在某处引发另一个错误。

话虽这么说,你在这里做的事情已经有人做过了。您可以使用 LoginRequiredMixin [Django-doc]:

from django.views.generic.edit import CreateView
from django.contrib.auth.mixins import <b>LoginRequiredMixin</b>

class MyCreateView(<b>LoginRequiredMixin</b>, CreateView):
    # ...

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid()

你要找的已经是内置的Django了,所以这里不用再造轮子了:login_required decorator and LoginRequired Mixin

你的方法是错误的,因为你重写了__init__;如果您想在 执行 视图之前进行检查,您可能需要考虑覆盖 dispatch()

def dispatch(self, request, *args, **kwargs):
    if request.user.is_authenticated:
        return super().dispatch(request, *args, **kwargs)
    return redirect()