Исключить поля в Django admin для пользователей, отличных от суперпользователя
У меня есть простой класс MyUser
с PermissionsMixin
. user.is_superuser
равно True
только для суперпользователей. Я хотел бы сделать что-то похожее на это в admin.py
:
if request.user.is_superuser:
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Permissions', {'fields': ('is_admin','is_staff')}),
('Place', {'fields': ('place',)}),
('Important dates', {'fields': ('last_login',)}),
)
else:
fieldsets = (
(None, {'fields': ('email', 'password')}),
#('Permissions', {'fields': ('is_admin','is_staff')}),
('Place', {'fields': ('place',)}),
('Important dates', {'fields': ('last_login',)}),
)
В принципе, я хочу, чтобы мои пользователи могли создавать других пользователей, но не предоставляли им права администратора или других. Только суперпользователи должны это сделать.
Ответы
Ответ 1
Если вы правильно поняли, что вы хотите сделать, это переопределить метод get_form для ModelAdmin. Основываясь на примере из документации django, он будет выглядеть примерно так:
class MyUserAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
self.exclude = []
if not request.user.is_superuser:
self.exclude.append('Permissions') #here!
return super(MyUserAdmin, self).get_form(request, obj, **kwargs)
Теперь вам может понадобиться немного взломать и, возможно, переопределить метод сохранения. Я сделал что-то подобное не так давно, это не так сложно (и документы фантастичны).
Возможно, будет более простое решение, но ваш вопрос будет общим, и вы не разделили свою модель пользователя, поэтому я не могу точно сказать, как это можно сделать. Надеюсь, это поможет!
Ответ 2
Принятый ответ близок, но, как указывают другие, get_form вызывается несколько раз в том же экземпляре модели администратора, и экземпляр повторно используется, поэтому вы можете в итоге повторить поля или другие пользователи, увидев поля после self.fields изменен. Попробуйте это в Django <= 1.6:
class MyAdmin(admin.ModelAdmin):
normaluser_fields = ['field1','field2']
superuser_fields = ['special_field1','special_field2']
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
self.fields = self.normaluser_fields + self.superuser_fields
else:
self.fields = self.normaluser_fields
return super(MyAdmin, self).get_form(request, obj, **kwargs)
Похоже, Django 1.7 вводит метод get_fields(), который вы можете переопределить, что намного лучше:
https://github.com/django/django/blob/d450af8a2687ca2e90a8790eb567f9a25ebce85b/django/contrib/admin/options.py#L276
Ответ 3
Согласно Django Docs, правильный способ - создать ModelForm для суперпользователей, а другой для обычных пользователей. Затем вы указываете каждую форму в методе get_form вашего ModelAdmin:
class MyModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
kwargs['form'] = MySuperuserForm
else:
kwargs['form'] = MyNormalForm
return super(MyModelAdmin, self).get_form(request, obj, **kwargs)
Ответ 4
Начиная Django 1.7, вы можете заменить базовый класс своего администратора модели чем-то вроде:
class SuperuserAwareModelAdmin(admin.ModelAdmin):
superuser_fields = None
superuser_fieldsets = None
def get_fieldsets(self, request, obj = None):
if request.user.is_superuser and self.superuser_fieldsets:
return (self.fieldsets or tuple()) + self.superuser_fieldsets
return super(SuperuserAwareModelAdmin, self).get_fieldsets(request, obj)
def get_fields(self, request, obj = None):
if request.user.is_superuser and self.superuser_fields:
return (self.fields or tuple()) + self.superuser_fields
return super(SuperuserAwareModelAdmin, self).get_fields(request, obj)
Пример:
class MyModelAdmin(SuperuserAwareModelAdmin):
superuser_fieldsets = (
(_('Permissions'), {'fields': ('is_staff', )}),
)
Базовый класс SuperuserAwareModelAdmin
также может быть создан как mixin.
Ответ 5
Django теперь имеет get_exclude
метод на ModelAdmin для исключения полей программно.
Он принимает текущий запрос и объект (если есть) в качестве аргумента. Вы можете поставить проверку на аргумент запроса, чтобы увидеть, являются ли они суперпользователем, и проверить
class MyModelAdmin(admin.ModelAdmin):
def get_exclude(self, request, obj=None):
excluded = super().get_exclude(request, obj) or [] # get overall excluded fields
if not request.user.is_superuser: # if user is not a superuser
return excluded + ['extra_field_to_exclude']
return excluded # otherwise return the default excluded fields if any