[Answered ]-Multilevel user admin in django

1👍

First of all edit your Role model to use Django’s Group model

from django.contrib.auth.models import Group

class Role(models.Model):
    name = models.CharField(max_length=100, unique=True)
    group = models.OneToOneField(Group, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

and in your admin.py try to define the default roles and their permissions

from django.contrib import admin
from django.contrib.auth.models import Group, Permission
from .models import Role

admin.site.unregister(Group)

@admin.register(Role)
class RoleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        #create or update the associated group with the same name as the role
        group, created = Group.objects.get_or_create(name=obj.name)
        obj.group = group
        obj.save()

        #assign the permissions to the group
        permissions = Permission.objects.filter(custom_users__role=obj)
        group.permissions.set(permissions)

        #update the associated custom users' groups
        custom_users = obj.custom_users.all()
        for custom_user in custom_users:
            custom_user.groups.add(group)

you have to also edit your CustomUser model to remove the role field and use the groups field instead

class CustomUser(AbstractBaseUser, PermissionsMixin):
    #rest of your code

    groups = models.ManyToManyField(Group, blank=True,
                                    related_name='custom_users')

    #rest of your code

and create a through model CustomerCustomUser to link Customer and CustomUser models

class CustomerCustomUser(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    custom_user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    role = models.ForeignKey(Role, on_delete=models.CASCADE)

and finally edit your Customer model to use the CustomerCustomUser model

class Customer(AbstractPerson):
    custom_users = models.ManyToManyField(CustomUser,
                                          through=CustomerCustomUser)

and now each customer can have multiple custom users with different roles, and they will inherit the permissions assigned to their respective roles!

UPDATE

according to your comment, you can add a related_name argument to the user_permissions field in your CustomUser model, because it will give a unique reverse accessor name for the user_permissions field in your CustomUser model, and avoiding the clash with the auth.User model!

user_permissions = models.ManyToManyField(
    Permission,
    blank=True,
    related_name='custom_user_permissions'
)

UPDATE 2

According to your comment, the error you are getting is because you are trying to assign a role to a CustomUser instance using an email address instead of a CustomUser instance itself,so please make sure that you are passing a CustomUser instance when assigning a role to a user

something like this :

custom_user = CustomUser.objects.get(email="m@y.com")
role = Role.objects.get(name="customer")
custom_user.role = role
custom_user.save()

UPDATE 3

according to your comment,to re-register the default Group model in the Django admin for the superuser,add this 3 lines into admin.py, because by calling admin.site.register(Group), you are re-registering the Group model in the Django admin interface!

from django.contrib import admin
from django.contrib.auth.models import Group

admin.site.register(Group)

Leave a comment