Django自定义群组模型的权限与视图逻辑实现问题
Django自定义群组模型权限与逻辑优化
问题1:修正创建者操作逻辑 + 限制群组查看范围
1.1 禁止创建者移出自己
可以通过Admin或前端表单层面控制,确保创建者始终在成员列表中:
- Admin端处理:重写
save_model方法自动将创建者加入成员,同时在表单中限制无法移除自己@admin.register(MyGroup) class MyGroupAdmin(admin.ModelAdmin): # 原有配置... def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) # 确保创建者始终在成员列表 if obj.created_by == request.user and request.user not in obj.members.all(): obj.members.add(request.user) def formfield_for_manytomany(self, db_field, request, **kwargs): field = super().formfield_for_manytomany(db_field, request, **kwargs) if db_field.name == 'members': obj = self.get_object(request, request.resolver_match.kwargs.get('object_id')) if obj and obj.created_by == request.user: # 移除选择框中的创建者选项,防止被移除 field.queryset = field.queryset.exclude(id=obj.created_by.id) return field
1.2 限制仅成员/创建者可查看群组
- 自定义模型管理器:封装过滤逻辑,方便在视图或Admin中调用
from django.db.models import Q class MyGroupManager(models.Manager): def for_user(self, user): # 返回当前用户是创建者或成员的群组 return self.filter(Q(created_by=user) | Q(members__in=[user])) # 在MyGroup模型中替换默认管理器 class MyGroup(models.Model): # 原有字段... objects = MyGroupManager() - 视图中使用:在列表/详情视图中过滤查询集
class MyGroupListView(ListView): model = MyGroup def get_queryset(self): return MyGroup.objects.for_user(self.request.user) - Admin端过滤:重写
get_queryset限制Admin中可见的群组@admin.register(MyGroup) class MyGroupAdmin(admin.ModelAdmin): def get_queryset(self, request): qs = super().get_queryset(request) if request.user.is_superuser: return qs return qs.filter(Q(created_by=request.user) | Q(members=request.user))
问题2:实现自定义权限控制
2.1 查看权限:仅创建者或成员可查看
- Admin端控制:重写
has_view_permission方法@admin.register(MyGroup) class MyGroupAdmin(admin.ModelAdmin): def has_view_permission(self, request, obj=None): if not obj: return super().has_view_permission(request, obj) # 判断当前用户是否是创建者或成员 return obj.created_by == request.user or request.user in obj.members.all() - 视图端控制:在详情视图中校验权限
from django.core.exceptions import PermissionDenied from django.views.generic import DetailView class MyGroupDetailView(DetailView): model = MyGroup def get_object(self, queryset=None): obj = super().get_object(queryset) if obj.created_by != self.request.user and self.request.user not in obj.members.all(): raise PermissionDenied() return obj
2.2 编辑权限:仅创建者、Staff或超级用户可编辑
- Admin端控制:重写
has_change_permission方法@admin.register(MyGroup) class MyGroupAdmin(admin.ModelAdmin): def has_change_permission(self, request, obj=None): if not obj: return super().has_change_permission(request, obj) # 满足任一条件即可编辑:超级用户、Staff、创建者 return request.user.is_superuser or request.user.is_staff or obj.created_by == request.user - 视图端控制:使用装饰器或视图内判断
from django.contrib.auth.decorators import user_passes_test from django.utils.decorators import method_decorator def can_edit_group(user, group): return user.is_superuser or user.is_staff or group.created_by == user @method_decorator(user_passes_test(lambda u: u.is_authenticated), name='dispatch') class MyGroupUpdateView(UpdateView): model = MyGroup fields = ['name', 'members'] def dispatch(self, request, *args, **kwargs): self.object = self.get_object() if not can_edit_group(request.user, self.object): raise PermissionDenied() return super().dispatch(request, *args, **kwargs)
关键说明
模型方法确实无法直接访问request.user,所以权限逻辑需要放在视图、Admin类、自定义管理器或装饰器中——这些场景能直接获取到请求对象,进而拿到当前登录用户。
内容的提问来源于stack exchange,提问作者user13698713
相关产品推荐
相关产品推荐

