Django按客户限制记录访问:代码误限制所有内容的问题排查
问题排查与修正方案
核心问题分析
你的代码存在两个关键错误,导致所有用户都被拦截:
- 错误地将
request.user.customer与模型类的字段定义Infringement.customer做对比,而非当前请求对应的Infringement实例的customer属性。类的字段和用户关联的customer对象永远不可能相等,因此这个判断始终为真,直接返回禁止访问。 - 权限校验逻辑写在获取具体
Infringement实例之前,此时还未拿到对应ID的记录,根本无法完成有效校验。
正确实现方式
步骤1:调整逻辑顺序,先获取实例再做校验
先通过pk获取对应的Infringement记录,再对比该记录的customer与当前用户关联的customer是否一致。
步骤2:处理实例不存在的情况(可选但推荐)
用get_object_or_404替代get,避免因无效ID抛出500错误,同时返回更友好的404页面。
修正后的完整代码
from django.shortcuts import get_object_or_404, redirect, render from django.contrib.auth.decorators import login_required from .models import Infringement, Note @login_required(login_url='login') def infringement(request, pk): # 先获取对应实例,不存在则返回404 infringement = get_object_or_404(Infringement, id=pk) # 校验当前用户的customer是否和实例的customer一致 if request.user.customer != infringement.customer: return HttpResponse('You are not allowed here!!') notes = infringement.note_set.all().order_by('-created') if request.method == "POST": Note.objects.create( customer=request.user.customer, user=request.user, infringement=infringement, body=request.POST.get('body') ) return redirect('infringement', pk=infringement.id) context = {'infringement': infringement, 'notes': notes} return render(request, 'base/infringements.html', context)
额外优化建议
- 可将权限校验逻辑封装成自定义装饰器,方便在多个视图中复用,减少重复代码。
- 如果需要更复杂的权限控制,推荐使用Django自带的
PermissionRequiredMixin(基于类的视图)或第三方库实现精细化权限管理。
内容的提问来源于stack exchange,提问作者Farid
相关产品推荐
相关产品推荐

