Django ListView:如何展示指定条目并保护其余数据?
解决方法
核心思路是在视图层面加入权限校验逻辑,确保用户只能访问自己有权限查看的Squadra条目,避免通过篡改URL参数越权访问。以下是几种具体实现方式:
1. 重写ListView的get_queryset方法,结合用户权限过滤
把过滤逻辑移到视图内部,同时校验用户是否有权限访问对应tipo的条目:
from django.views.generic import ListView from django.contrib.auth.mixins import LoginRequiredMixin from .models import Squadra class SquadraTableListView(LoginRequiredMixin, ListView): model = Squadra template_name = 'your_template.html' def get_queryset(self): # 获取URL传入的tipo参数 requested_tipo = self.kwargs.get('squadra') # 示例1:仅允许超级用户访问tipo=3,普通用户只能访问1/2 if not self.request.user.is_superuser and requested_tipo == 3: return Squadra.objects.none() # 示例2:如果Squadra和用户有直接关联(比如有user字段),过滤用户自己的条目 # return Squadra.objects.filter(tipo=requested_tipo, user=self.request.user) # 基础校验:限制用户只能访问预设的合法tipo allowed_tipos = [1, 2] if requested_tipo not in allowed_tipos: return Squadra.objects.none() return Squadra.objects.filter(tipo=requested_tipo)
2. 用Django权限系统做细粒度控制
如果需要灵活分配不同tipo的访问权限,可以自定义模型权限,再在视图中校验:
首先在models.py中定义自定义权限:
class Squadra(models.Model): tipo = models.IntegerField(choices=TIPO_SQUADRA, default=1) # ...其他字段 class Meta: permissions = [ ("view_tipo_1", "允许查看tipo=1的队伍"), ("view_tipo_2", "允许查看tipo=2的队伍"), ("view_tipo_3", "允许查看tipo=3的队伍"), ]
然后在视图中检查权限:
class SquadraTableListView(LoginRequiredMixin, ListView): model = Squadra template_name = 'your_template.html' def get_queryset(self): requested_tipo = self.kwargs.get('squadra') # 拼接对应的权限字符串 required_perm = f"your_app.view_tipo_{requested_tipo}" # 校验用户是否拥有该权限 if not self.request.user.has_perm(required_perm): return Squadra.objects.none() return Squadra.objects.filter(tipo=requested_tipo)
3. 直接返回403禁止访问(更严格的方式)
如果用户无权限,直接抛出403错误,而不是返回空页面:
from django.views.generic import ListView from django.contrib.auth.mixins import LoginRequiredMixin from django.core.exceptions import PermissionDenied from .models import Squadra class SquadraTableListView(LoginRequiredMixin, ListView): model = Squadra template_name = 'your_template.html' def get_queryset(self): requested_tipo = self.kwargs.get('squadra') # 示例:仅"AdminGroup"组的用户能访问tipo=3 if requested_tipo == 3 and not self.request.user.groups.filter(name='AdminGroup').exists(): raise PermissionDenied return Squadra.objects.filter(tipo=requested_tipo)
额外建议
如果不想让用户直接看到tipo的数值,可以用UUID、slug等隐蔽标识符替代URL中的数字参数,但这只是辅助手段,核心还是要做好权限校验。
内容的提问来源于stack exchange,提问作者Attilio
相关产品推荐
相关产品推荐

