Django中如何禁止非管理员用户调用模型delete()方法?
Django中控制模型delete()方法的权限:管理员真删,非管理员软删
可以实现这个需求,但你提供的代码存在几处错误,比如无法获取当前用户、语法错误、方法调用逻辑错误等,以下是修正后的完整实现方案:
第一步:修正模型代码,重写delete方法
首先修正模型字段的拼写错误(max_lenght改为max_length),并给delete方法添加用户参数,实现权限判断逻辑:
from django.utils import timezone class Product(models.Model): name = models.CharField(max_length=200) show = models.BooleanField(default=True) logs = models.TextField(blank=True) # 允许日志为空,避免初始化报错 def delete(self, user=None, *args, **kwargs): # 管理员用户执行真实删除 if user and user.is_superuser: super().delete(*args, **kwargs) else: # 非管理员执行软删除:标记show为False,追加操作日志 self.show = False current_time = timezone.now().strftime("%d.%m.%Y %H:%M:%S") # 拼接日志内容,保留原有日志 log_content = f"用户{user.username if user else '匿名用户'}尝试删除,执行软删除,时间:{current_time}\n" self.logs += log_content self.save(*args, **kwargs)
第二步:在视图中调用delete方法时传递用户参数
在业务视图里调用delete时,需要把当前请求的用户传进去,这样模型才能判断权限:
from django.shortcuts import get_object_or_404, redirect from .models import Product def delete_product(request, pk): product = get_object_or_404(Product, pk=pk) # 传入当前请求的user对象 product.delete(user=request.user) return redirect('product_list') # 重定向到产品列表页
第三步:适配Django Admin的删除操作
默认情况下,Django Admin的删除动作不会调用单个实例的delete方法(Admin使用批量删除逻辑),如果要让Admin也遵循这个权限规则,需要重写Admin类的delete_model方法:
from django.contrib import admin from .models import Product class ProductAdmin(admin.ModelAdmin): def delete_model(self, request, obj): # 调用我们重写的delete方法,传入当前管理员用户 obj.delete(user=request.user) admin.site.register(Product, ProductAdmin)
注意事项
- 批量删除处理:如果是通过QuerySet执行批量删除(比如
Product.objects.filter(...).delete()),这种方式不会调用单个实例的delete方法,需要额外重写QuerySet的delete方法,或者在业务逻辑中限制非管理员的批量删除权限。 - 日志追加:示例中采用追加日志的方式,避免覆盖原有操作记录,如果你需要覆盖旧日志,直接赋值
self.logs = log_content即可。
内容的提问来源于stack exchange,提问作者Maddie Graham
相关产品推荐
相关产品推荐

