Django中仅允许对象所有者操作的Update&Delete视图实现问题
解决Django中仅对象所有者可修改/删除的权限问题
嘿,我来帮你搞定这个视图权限控制的问题!你目前的代码已经在尝试用get_queryset过滤当前用户的车辆,但这还不够——要是用户手动修改URL里的车辆ID(比如把/car/update/1/改成/car/update/2/),还是能访问不属于自己的车辆。咱们得把权限控制做扎实,下面给你几种靠谱的实现方式:
方法1:使用UserPassesTestMixin(推荐)
Django自带的UserPassesTestMixin是处理这类对象级权限的绝佳工具,它会在视图处理请求前先检查权限,逻辑清晰且易维护。
第一步:导入Mixin
首先在视图文件顶部导入所需模块:
from django.contrib.auth.mixins import UserPassesTestMixin from django.contrib import messages
第二步:修改Update视图
把UserPassesTestMixin加到你的UpdateCar视图继承链最前面,然后实现test_func方法检查用户是否为车辆所有者:
class UpdateCar(UserPassesTestMixin, SuccessMessageMixin, UpdateView): model = Car form_class = AddNewCarForm template_name = 'c2crental/car/update_car.html' success_url = reverse_lazy('c2crental:list_user_cars') success_message = _("Car has been updated.") def test_func(self): # 获取当前要操作的车辆对象 car = self.get_object() # 验证当前用户是否是车辆所有者 return car.owner == self.request.user # 可选:自定义权限不足时的提示和跳转 def handle_no_permission(self): messages.error(self.request, _("你没有权限修改这辆车!")) return redirect('c2crental:list_user_cars')
第三步:修改Delete视图
Delete视图的处理逻辑类似,还要注意默认DeleteView不会自动显示success_message,需要额外重写delete方法:
class DeleteCar(UserPassesTestMixin, DeleteView): model = Car success_url = reverse_lazy('c2crental:list_user_cars') success_message = _("Car has been deleted.") def test_func(self): car = self.get_object() return car.owner == self.request.user def handle_no_permission(self): messages.error(self.request, _("你没有权限删除这辆车!")) return redirect('c2crental:list_user_cars') # 让DeleteView支持success_message def delete(self, request, *args, **kwargs): messages.success(self.request, self.success_message) return super().delete(request, *args, **kwargs)
方法2:重写dispatch方法
如果你不想用Mixin,也可以直接重写视图的dispatch方法,在请求进入视图核心逻辑前做权限检查:
class UpdateCar(SuccessMessageMixin, UpdateView): # 原有属性保持不变... def dispatch(self, request, *args, **kwargs): # 先获取要操作的对象 self.object = self.get_object() # 检查所有者权限 if self.object.owner != request.user: messages.error(request, _("你没有权限修改这辆车!")) return redirect('c2crental:list_user_cars') # 权限通过,继续执行原逻辑 return super().dispatch(request, *args, **kwargs)
额外提醒
确保你的Car模型已经正确关联了用户作为所有者:
from django.contrib.auth.models import User class Car(models.Model): owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_cars') # 你的其他车辆字段...
这样修改后,不管用户是通过页面按钮还是手动篡改URL,都只能操作自己名下的车辆啦!
内容的提问来源于stack exchange,提问作者Dombi
相关产品推荐
相关产品推荐

