Как использовать пользовательскую форму ModelForm в админке пользователя

Я пытаюсь ограничить возможности стандартного пользователя в админке приложения Django, чтобы избежать возможности эскалации привилегий.User

Я попробовал подход, упомянутый в документации: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_form

class UserAdmin(BaseUserAdmin):
    form = UserForm
    inlines = (UserProfileInline,)

    def get_form(self, request, obj=None, **kwargs):
       if request.user.is_superuser:
           kwargs["form"] = SuperUserForm
       return super().get_form(request, obj, **kwargs)

class UserForm(ModelForm):
    class Meta:
        model = User
        exclude = ("is_superuser",) # it is just an example


class SuperUserForm(ModelForm):
    class Meta:
        model = User
        fields = "__all__

К сожалению, это приводит к такой ошибке:

"Key 'is_superuser' not found in 'UserForm'. Choices are: date_joined, email, first_name, groups, is_active, is_staff, last_login, last_name, password, user_permissions, username."

Если бы я решил исключить "группы":

"Key 'groups' not found in 'UserForm'. Choices are: date_joined, email, first_name, is_active, is_staff, is_superuser, last_login, last_name, password, user_permissions, username."

В итоге у меня получился совершенно другой подход:

class UserAdmin(BaseUserAdmin):

    def has_change_permission(self, request, obj=None):
        if obj != request.user and not request.user.is_superuser:
            return False
        return True

    def changelist_view(self, request, extra_context=None):
        if request.user.is_superuser:
            return super().changelist_view(request, extra_context)

        return HttpResponseRedirect(
            reverse(
                "admin:%s_%s_change" % (self.model._meta.app_label, self.model._meta.model_name),
                args=(request.user.id,),
            )
        )

    def get_fieldsets(self, request, obj=None):
        fieldsets = list(super().get_fieldsets(request, obj))
        if request.user.is_superuser:
            return fieldsets

        return [
            (None, {"fields": ("username", "password")}),
            ("Personal info", {"fields": ("first_name", "last_name", "email")}),
        ]
    

Я не знаю, является ли это "по-джанговски", но кажется, что это работает так, как ожидалось.

Вернуться на верх