Using guardian
in a django
project, I want the admins to be able to assign object permissions over the admin interface. With guardian
this is possible, but the Object permissions form in the admin interface, the Group field is a TextField
. How do I make it a ChoiceField
with all existing groups as choices?
Is there a solution that only requires adding code in the admin.py
file of the app or do we have to overwrite some guardian
code? How can we do it without messing with the functionality of guardian
?
This is my admin.py
file:
from django.contrib import admin
from .models import MyModel
from guardian.admin import GuardedModelAdmin
class MyModelAdmin(GuardedModelAdmin):
pass
admin.site.register(MyModel, MyModelAdmin)
Here is the solution that works like a charm. First subclass the GuardedModelAdminMixin
from guardian.admin import GuardedModelAdmin, GuardedModelAdminMixin
class CustomGuardedModelAdminMixin(GuardedModelAdminMixin):
def get_obj_perms_group_select_form(self, request):
"""
Returns form class for selecting a group for permissions management. By default :form:`GroupManage` is
returned. This enhancement returns GroupModelManage instead, allowing admins to get a queryset of groups.
"""
return GroupModelManage
Then define the ModelManager for groups with overriding the clean_group function:
class GroupModelManage(forms.Form):
"""
Extends the Django Guardian GroupManage class to select User from a query containing all
User objects rather than a blank input CharField.
"""
group = forms.ModelChoiceField(queryset=Group.objects.all())
def clean_group(self):
"""
Returns ``Group`` instance based on the given group name.
"""
try:
return self.cleaned_data['group']
except Group.DoesNotExist:
raise forms.ValidationError(self.fields['group'].error_messages['does_not_exist'])
Finally, use the new Mixin in your Admin class:
class MyModelAdmin(CustomGuardedModelAdminMixin, admin.ModelAdmin):
pass
admin.site.register(MyModel, MyModelAdmin)
To do custom querysets on the user level, use this function in the new mixin:
def get_obj_perms_user_select_form(self, request):
return UserModelManage
A full example is here: LINK