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

如何编写Django下仅允许内容创建者操作资源的自定义装饰器

Django 实现仅内容创建者可操作的自定义装饰器

1. 编写自定义书籍作者校验装饰器

from django.http import HttpResponseForbidden
from django.shortcuts import get_object_or_404
from .models import Book

def is_book_writer(function):
    def wrap(request, *args, **kwargs):
        # 从视图URL参数中获取书籍主键
        book = get_object_or_404(Book, id=kwargs["pk"])
        # 校验当前登录用户是否为该书籍的对应作者
        if request.user == book.writer.profile.user:
            return function(request, *args, **kwargs)
        # 校验不通过返回403禁止访问
        return HttpResponseForbidden("您没有权限操作该书籍资源")
    # 保留原函数的元信息
    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap

2. 在类视图中挂载装饰器

和你现有使用的其他装饰器用法一致,用method_decorator包裹后绑定到dispatch方法即可:

@method_decorator(login_required(login_url='core:login'), name='dispatch')
@method_decorator(allowed_users(allowed_roles=['writer']), name='dispatch')
# 新增作者校验装饰器
@method_decorator(is_book_writer, name='dispatch')
class BookDeleteView(BSModalDeleteView):
    model = Book
    template_name = 'book/book_delete.html'
    success_message = 'Success: book was deleted.'
    success_url = reverse_lazy('core:book_list')

3. 可选优化:通用化装饰器适配多模型

如果后续需要给其他模型也添加类似的所有者校验逻辑,可以改成可传参的通用装饰器,避免重复编码:

from django.http import HttpResponseForbidden
from django.shortcuts import get_object_or_404

def is_content_owner(model_class, owner_field_path):
    def decorator(function):
        def wrap(request, *args, **kwargs):
            target_obj = get_object_or_404(model_class, id=kwargs["pk"])
            # 按指定路径读取所有者字段
            owner = target_obj
            for field in owner_field_path.split("."):
                owner = getattr(owner, field)
            if request.user == owner:
                return function(request, *args, **kwargs)
            return HttpResponseForbidden("您没有权限操作该资源")
        wrap.__doc__ = function.__doc__
        wrap.__name__ = function.__name__
        return wrap
    return decorator

使用时直接传入对应模型和所有者字段路径即可:

@method_decorator(is_content_owner(Book, "writer.profile.user"), name='dispatch')

注意事项

  • 请确保URL路由中传递给视图的主键参数名和装饰器中读取的参数名一致,如果你路由中使用book_id而非pk作为参数名,需要将kwargs["pk"]修改为kwargs["book_id"]
  • 装饰器执行顺序为从上到下,建议将登录校验、角色校验放在所有者校验之前,减少无效数据库查询

内容的提问来源于stack exchange,提问作者ahmed belkhiri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 01:30:02