Django Admin如何创建自定义权限 限制用户仅访问外键关联数据
Django Admin 实现关联用户的行级数据权限方案
默认Django为模型自动生成的add/change/delete/view属于模型级权限,用户只要获得对应权限就能访问模型下的全部数据,要实现「用户仅查看外键关联到自身的对象」的效果,不需要引入第三方依赖,直接重写模型Admin类的对应方法即可,以题目中的Book模型为例,完整实现如下:
核心实现逻辑
一共需要做三层拦截,覆盖所有访问场景:
- 列表页查询集过滤:只返回关联到当前用户的对象
- 单对象权限校验:防止用户通过手动拼接URL访问不属于自己的对象详情、编辑、删除页
- 新增数据自动绑定:保存数据时自动将关联用户字段设为当前登录用户,避免越权绑定到其他用户
完整代码示例
在对应app的admin.py中添加如下代码:
from django.contrib import admin from .models import Book @admin.register(Book) class BookAdmin(admin.ModelAdmin): # 编辑/新增页不展示作者选择项,避免用户越权修改所属作者 exclude = ('author',) def get_queryset(self, request): """重写列表页查询集,过滤非当前用户的图书数据""" qs = super().get_queryset(request) # 超级用户可查看所有数据,不受限制 if request.user.is_superuser: return qs # 普通用户仅返回作者为当前登录用户的图书 return qs.filter(author=request.user) def has_view_permission(self, request, obj=None): """校验单对象查看权限""" base_perm = super().has_view_permission(request, obj) if not base_perm: return False # 列表页访问直接放行,由get_queryset做数据过滤 if obj is None: return True # 仅作者本人或超管可查看单本图书详情 return obj.author == request.user or request.user.is_superuser def has_change_permission(self, request, obj=None): """校验单对象编辑权限""" base_perm = super().has_change_permission(request, obj) if not base_perm: return False if obj is None: return True return obj.author == request.user or request.user.is_superuser def has_delete_permission(self, request, obj=None): """校验单对象删除权限""" base_perm = super().has_delete_permission(request, obj) if not base_perm: return False if obj is None: return True return obj.author == request.user or request.user.is_superuser def save_model(self, request, obj, form, change): """保存图书时自动绑定当前登录用户为作者""" # 仅新增时设置作者,避免编辑时修改原有归属 if not change: obj.author = request.user super().save_model(request, obj, form, change)
使用说明
- 权限分配逻辑和原生Django权限完全一致,直接给对应用户分配Book模型的查看、编辑等基础权限即可,不需要额外创建自定义权限
- 超级用户默认拥有全部权限,可查看、编辑所有图书数据,符合常规后台使用逻辑
- 所有访问入口均做了权限拦截,不存在越权访问漏洞
内容的提问来源于stack exchange,提问作者atropa belladona
相关产品推荐
相关产品推荐

