我要制作一个Web应用程序,类似于用户层级结构。我想这样做:
1. 超级用户创建具有某些权限的用户,这些用户也可以添加拥有它们自己权限的用户。这些用户也可以添加用户,以此类推。没有人应该能够编辑权限更高的用户。
问题在于,我希望将Django管理面板提供给所有这些用户使用。这种做法是否可行?我已经搜索了网络,并没有找到解决方案。谢谢建议。
问题在于,我希望将Django管理面板提供给所有这些用户使用。这种做法是否可行?我已经搜索了网络,并没有找到解决方案。谢谢建议。
is_staff=True
标志。允许未与您的组织相关联的用户访问管理员永远不是一个好主意。认真对待,不要这样做。如果这是您的计划,请另寻他路。UserCreationForm
和 UserChangeForm
(Auth 在其管理员中使用两个单独的表单)。覆盖每个表单的 __init__
方法以从 kwargs
中提取 request
(表单默认不会获取请求,但在这里是必要的,因此您需要进行一些变通处理)。然后,子类化默认的 UserAdmin
,将 form
和 add_form
设置为新表单,并覆盖 get_form
(以传递 request
)和每个 has_foo_permission
方法以限制访问。还需要重写 queryset
方法,以便用户只能在管理员中看到他们可以修改的用户。from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import Group, Permission
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
pass
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(CustomUserCreationForm, self).__init__(*args, **kwargs)
# Limit groups and permissions to those that belong to current user
if self.request and not self.request.user.is_superuser:
self.fields['groups'].queryset = self.request.user.groups.all()
self.fields['user_permissions'].queryset = self.request.user.user_permissions.all()
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
pass
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(CustomUserChangeForm, self).__init__(*args, **kwargs)
# Limit groups and permissions to those that belong to current user
if self.request and not self.request.user.is_superuser:
self.fields['groups'].queryset = self.request.user.groups.all()
self.fields['user_permissions'].queryset = self.request.user.user_permissions.all()
class CustomUserAdmin(UserAdmin):
form = UserChangeForm
add_form = UserCreationForm
limited_fieldsets = ( # Copied from default `UserAdmin`, but removed `is_superuser`
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
(_('Groups'), {'fields': ('groups',)}),
)
def get_fieldsets(self, request, obj=None):
if not obj:
return self.add_fieldsets
elif not request.user.is_superuser:
return self.limited_fieldsets
else:
return super(CustomUserAdmin, self).get_fieldsets(request, obj)
def get_form(self, request, obj=None, **kwargs):
"""Return a metaclass that will automatically pass `request` kwarg into the form"""
ModelForm = super(LinkAdmin, self).get_form(request, obj, **kwargs)
class ModelFormMetaClass(ModelForm):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return ModelForm(*args, **kwargs)
return ModelFormMetaClass
def has_add_permission(self, request):
"""
If not superuser only allow add if the current user has at least some
groups or permissions. (they'll have to be able to at least have something
to assign the user they are creating).
"""
if not request.user.is_superuser:
if not request.user.groups.exists() or not request.user.user_permissions.exist():
return False
return True
def has_change_permission(self, request, obj=None):
"""
If not superuser, current user can only modify users who have a subset of the
groups and permissions they have.
"""
if obj and not request.user.is_superuser:
# Check that all of the object's groups are in the current user's groups
user_groups = list(request.user.groups.all())
for group in obj.groups.all():
try:
user_groups.index(group)
except ValueError:
return False
# Check that all of the object's permissions are in the current user's permissions
user_permissions = list(request.user.user_permissions.all())
for permission in obj.user_permissions.all():
try:
user_permissions.index(permission)
except ValueError:
return False
return True
def has_delete_permission(self, request, obj=None):
"""Same logic as `has_change_permission`"""
return self.has_change_permission(request, obj)
def queryset(self, request):
qs = super(CustomUserAdmin, self).queryset(self, request)
if request.user.is_superuser:
return qs
else:
"""
This part is a little counter-intuitive. We're going to first get a
list of all groups/permissions that don't belong to the user, and
then use that to exclude users that do have those from the queryset.
"""
user_group_pks = [g.pk for g request.user.groups.values('pk')]
exclude_groups = Group.objects.exclude(pk__in=user_group_pks)
user_permission_pks = [p.pk for p in request.user.user_permissions.values('pk')]
exclude_permissions = Permission.objects.exclude(pk__in=user_permission_pks)
return qs.exclude(groups__in=exclude_groups, user_permissions__in=exclude_permissions)
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
Django内置了一个用户层次结构维护系统 - Django-RBAC。
RBAC代表基于角色的访问控制。它是一种根据层次结构创建和管理权限的机制。您只需要稍微学习一下就可以了。