我想限制对某些具有属性的详细文章页面的访问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)