Каждый пользователь, которому понадобится доступ к администратору, должен иметь флаг is_staff=True
. никогда - хорошая идея разрешить пользователям, не связанным с вашей организацией, доступ к администратору. Серьезно, просто не делай этого. Если это твой план, найди другой.
Тем не менее, это может быть сделано, но это не для слабонервных. Там много вовлечено. Первый подкласс по умолчанию UserCreationForm
и UserChangeForm
(Auth использует две отдельные формы для своего администратора). Переопределите метод __init__
каждого для извлечения request
из kwargs
(формы не получают запрос по умолчанию, но это необходимо здесь, поэтому вы должны сделать небольшой обходной путь). Затем подкласс по умолчанию 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)