You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:26:25