I am trying to restrict users in groups from being able to change fields their group does not have permission to change. For example:
class StudentReferral(models.Model):
teacher = models.CharField(max_length=50)
referral_first_name = models.CharField(max_length=50)
referral_last_name = models.CharField(max_length=50)
accepted = models.BooleanField(blank=True)
Now the teachers are all in one user group and the person who accepts or declines the referral is in another user group. The teacher user group should only be able to edit the following fields: teacher
, referral_first_name
and referral_last_name
. The other user group should only be able to edit the accepted field. Both groups should be able to see all of the fields.
Is there something built into django that makes this possible or a custom way of doing this?
Override ModelAdmin.get_fieldsets
, and do something like the following:
class MyModelAdmin(admin.ModelAdmin):
...
fieldsets = (
... # Standard/all fields
)
teacher_fieldsets = (
... # Only fields teachers can see
)
def get_fieldsets(self, request, obj=None):
if request.user.groups.filter(name='Teachers').exists():
return self.teacher_fieldsets
else:
return super(MyModelAdmin, self).get_fieldsets(request, obj=obj)
EDIT
Sorry, I missed the bit about they should still be able to see all fields, just not edit them. I've left the original answer intact, as it might still be of use to you. For this, though, you'll need to override ModelAdmin.get_readonly_fields
:
class MyModelAdmin(admin.ModelAdmin):
...
readonly_fields = ('teacher', 'referral_first_name', 'referral_last_name')
teacher_readonly_fields = ('accepted',)
def get_readonly_fields(self, request, obj=None):
if request.user.groups.filter(name='Teachers').exists():
return self.teacher_readonly_fields
else:
return super(MyModelAdmin, self).get_readonly_fields(request, obj=obj)
I'm assuming here that the choices are only teacher or "other user". If there's other types to consider, or you don't want the fields limited at all in one circumstance, you might want to remove the readonly_fields
attribute and replace it with something like other_readonly_fields
, and branch accordingly (the default value for readonly_fields
is only those fields that have editable=False
on the model).
Also, be aware that if a field is required, you can't make it read-only as well. If some of these are required fields, you'll need to override ModelForm.__init__
as well, to make them not required in the circumstances where they will be read-only, which requires some extra hackery (ModelForm
doesn't have access to request
, normally):
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')
super(MyModelForm, self).__init__(*args, **kwargs)
if self.request is not None:
if self.request.user.groups.filter(name='Teachers').exists():
self.fields['accepted'].required = False
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
...
def get_form(self, request, obj=None, **kwargs):
ModelForm = super(MyModelAdmin, self).get_form(request, obj=obj, **kwargs)
class WrapperModelForm(ModelForm):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return ModelForm(*args, **kwargs)
return WrapperModelForm
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With