如何根据用户权限和模型属性值限制对 DetailView 的访问?

2024-04-30

我想限制对某些具有属性的详细文章页面的访问is_private=True。可以在文章列表中显示,但仅限有权限的用户view_private_articles必须能够访问文章详细视图。

模型.py:

class Article(models.Model):
    title = models.CharField(
        max_length=150,
    )
    is_private = models.BooleanField(
    default=False,
    )

视图.py:

class ArticleListView(LoginRequiredMixin,ListView):
    model = Article
    template_name = 'article_list.html'
    context_object_name = 'article_objects_list'
    login_url = 'login'

    class Meta:
        permissions = [
            ("view_private_articles", "Can view private articles"),
        ]

    def __str__(self):
        return self.value


class  ArticleDetailView(
        LoginRequiredMixin,
        PermissionRequiredMixin,
        DetailView):
    model = Article
    context_object_name = 'article_object'
    template_name = 'detail/article_detail.html'
    login_url = 'login'
    permission_required = 'view_private_articles'

正如您所注意到的,问题是该方法所描述的here https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#custom-permissions只能限制没有权限的用户view_private_articles查看所有文章的权限(不仅限于is_private=True属性)。

那么如何限制用户只能查看带有属性的文章is_private=True?

更新01 我尝试添加 UserPassesTestMixin 但没有结果:

class  ArticleDetailView(
        LoginRequiredMixin,
        PermissionRequiredMixin,
        UserPassesTestMixin,
        DetailView):
    model = Article
    context_object_name = 'article_object'
    template_name = 'detail/article_detail.html'
    login_url = 'login'
    permission_required = 'view_private_articles'

        def test_func(self):
        article_obj = self.get_object()
        user_obj = self.request.user
        if article_obj.is_private is True and user_obj.has_perms("view_private_articles"):
            return True
        else:
            return False

如果我的用户没有这样做,我仍然会收到 403 禁止view_private_articles权限无论是否有属性is_private或者不是因为 PermissionRequiredMixin。但是如果我删除 PermissionRequiredMixin,我的用户就没有view_private_articles权限可以访问详细文章。显然我写的方法很糟糕,但是如何正确呢?

UPDATE02 它的工作原理如下:

class  ArticleDetailView(
        LoginRequiredMixin,
        UserPassesTestMixin,
        DetailView):
    model = Article
    context_object_name = 'article_object'
    template_name = 'detail/article_detail.html'
    login_url = 'login'
    permission_required = 'view_private_articles'

        def test_func(self):
        article_obj = self.get_object()
        user_obj = self.request.user
        if article_obj.is_private is True and user_obj.has_perm("blog.view_private_articles"):
            return True
        return False

其中 blog-包含 model 的应用程序的名称。感谢@dirkgroten!

UPDATE03 也可以通过视图方法完成dispatch重写:

from django.core.exceptions import PermissionDenied

class  ArticleDetailView(
        LoginRequiredMixin,
        DetailView):
    model = Article
    context_object_name = 'article_object'
    template_name = 'detail/article_detail.html'
    login_url = 'login'

    def dispatch(self, request, *args, **kwargs):
        user_obj = self.request.user
        if not user_obj.has_perm("blog.view_private_articles"):
            raise PermissionDenied
        return super().dispatch(request,*args,**kwargs)

您可能也不想显示您的文章中的所有文章ListView。所以有两种不同的方法ListViewDetailView.

For the ListView你应该覆盖get_queryset()。在这里您可以根据用户发回不同的列表:

def get_queryset(self, **kwargs):
    qs = super().get_queryset(**kwargs)
    if self.request.user.is_staff:
        return qs
    if self.request.user.has_perm("view_private_articles"):
        return qs.filter(is_private=True)
    return qs.none()

For the DetailView, add a UserPassesTestMixin供您查看和使用get_object()验证用户是否允许查看特定对象:

 def test_func(self):
     return self.request.user.may_view(self.get_object())  # assuming you write a `may_view(article)` method on a `User` model.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何根据用户权限和模型属性值限制对 DetailView 的访问? 的相关文章

随机推荐