基于类的视图中如何进行超级用户认证

3

我正在开发一个博客项目,其中我添加了一个“添加文章”的功能,现在我希望只有超级用户才能添加文章,并且该页面只对超级用户可见。
第一种方法
Views.py

class AddPostView(CreateView):
    model = Post
    template_name = 'MainSite/add_post.html'
    fields = '__all__'

这是我的目前观点:我能够通过第二种方法对超级用户进行认证。
第二种方法

class AddPostView(View):
    def get(self,request):
        if request.user.is_superuser == True:
            return render(...)
        else:
            pass

我应该如何使用第一种方法来实现同样的结果?我尝试使用 LoginRequiredMixin,但是没有任何反应。我只是导入 LoginRequiredMixin 并像这样使用它。
class Addpost(CreateView,LoginRequiredMixin):
    ...

先提前感谢您的帮助和建议。

3个回答

3
你可以使用 UserPassesTestMixin 混合类。
from django.contrib.auth.mixins import UserPassesTestMixin

class AddPostView(<strong>UserPassesTestMixin</strong>, CreateView):
    # …
    
    def test_func(self):
        return self.request.user<strong>.is_superuser</strong>
    
    # …

您可以将此封装在混合器中:

from django.contrib.auth.mixins import UserPassesTestMixin

class AdminRequiredMixin(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.is_superuser

然后使用这个mixin:

class AddPostView(<strong>AdminRequiredMixin</strong>, CreateView):
    # …
    
    def test_func(self):
        return self.request.user<strong>.is_superuser</strong>
    
    # …

在继承层次结构中,Mixin应该放在实际视图之前:否则这些会出现在视图后面的方法解析顺序(MRO)中,因此很可能无法正确覆盖行为。

谢谢,这个方法可行,但是我该如何重定向到不同的页面呢?如果用户不是超级用户,我想要重定向到主页,目前它显示403错误。 - Roshan
@Roshan:你可以重写 def handle_no_permission 方法,并在那里 return redirect('name-of-some-view')。但是要重定向到登录URL。 - Willem Van Onsem
@WillamVanOnsem 谢谢,我明白了。关于编写基于类的视图,哪种方法更有效,方法1还是方法2?(抱歉,这个问题有点跑题) - Roshan
@Roshan:这并不重要(或者只有几毫秒的差距),如果你想将mixin应用于多个视图,第二种方法更好。例如,如果你想在两个、三个或更多的视图中实现这一点,你只需要有效地实现mixin一次,然后将其混合到其他视图中,从而避免再次重写相同的逻辑。 - Willem Van Onsem

2
class AddPostView(CreateView,LoginRequiredMixin):
    model = Post
    template_name = 'MainSite/add_post.html'
    fields = '__all__'
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_anonymous:
           return redirect_to_login(self.request.get_full_path(), self.get_login_url(), self.get_redirect_field_name())
        elif request.user.is_superuser:
            return render(.....)
        else
            return super(AddPostView, self).dispatch(request, *args, **kwargs)

1
使用method_decorator和user_passes_test来实现这个功能。
from django.views.generic import View
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import user_passes_test

class AddPostView(View):
    @method_decorator(user_passes_test(lambda u: u.is_superuser))
    def post(self, *args, **kwargs):
        pass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接