Cant activate permission for new users in site administrations

I am facing an issue with the admin panel and permissions after creating a new user with a defined role. The goal of the project is to assign specific roles to users (Director, Teacher, Student) and configure permissions accordingly through the admin panel.

  • For the Student: They should only be able to view their own grades and see the names of students (first name, last name, etc.).
  • For the Teacher: They should be able to view students and have permissions to add, edit, view, and delete grades.
  • For the Director: They should have full permissions to add, edit, view, and delete subjects, groups, students, and teachers.

However, my code is not functioning as expected. I’m unable to assign or manage permissions correctly for users with specific roles (When I log in with a user who has a role, such as Teacher/Director/Student, in the site administration I see the following message: “You don’t have permission to view or edit anything.” and nothing logs (nothing has been printed).

Please see my code below. Any help in identifying and resolving the issue would be greatly appreciated!

Thank you!

Here my admin.py:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser, Group1, Student, Subject, Grade
from .formsAdmin import CustomUserCreationForm, CustomUserChangeForm

@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
    add_form = CustomUserCreationForm
    form = CustomUserChangeForm
    model = CustomUser

    list_display = ('username', 'role', 'is_staff', 'is_active', 'is_superuser')
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        ('Personal Info', {'fields': ('first_name', 'last_name', 'email')}),
        ('Permissions', {'fields': ('role', 'is_staff', 'is_superuser', 'is_active')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'role', 'password1', 'password2'),
        }),
    )
    search_fields = ('username',)
    ordering = ('username',)

@admin.register(Group1)
class Group1Admin(admin.ModelAdmin):
    list_display = ('name', 'teacher',)
    search_fields = ('name',)
    ordering = ('name',)

    def has_view_permission(self, request, obj=None):
        print(f"Checking view permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role in ['teacher', 'director']

    def has_add_permission(self, request):
        print(f"Checking add permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'director'

    def has_change_permission(self, request, obj=None):
        print(f"Checking change permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'director'

    def has_delete_permission(self, request, obj=None):
        print(f"Checking delete permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'director'

@admin.register(Student)
class StudentAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'patronymic', 'user')

    def has_view_permission(self, request, obj=None):
        print(f"Checking view permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role in ['teacher', 'student', 'director']

    def has_add_permission(self, request):
        print(f"Checking add permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'director'

    def has_change_permission(self, request, obj=None):
        print(f"Checking change permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'director'

    def has_delete_permission(self, request, obj=None):
        print(f"Checking delete permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'director'

@admin.register(Subject)
class SubjectAdmin(admin.ModelAdmin):
    list_display = ('name', 'teacher')

    def has_view_permission(self, request, obj=None):
        print(f"Checking view permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role in ['teacher', 'director']

    def has_add_permission(self, request):
        print(f"Checking add permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'director'

    def has_change_permission(self, request, obj=None):
        print(f"Checking change permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'director'

    def has_delete_permission(self, request, obj=None):
        print(f"Checking delete permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'director'

@admin.register(Grade)
class GradeAdmin(admin.ModelAdmin):
    list_display = ('student', 'subject', 'grade')

    def has_view_permission(self, request, obj=None):
        print(f"Checking view permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role in ['teacher', 'student', 'director']

    def has_add_permission(self, request):
        print(f"Checking add permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'teacher'

    def has_change_permission(self, request, obj=None):
        print(f"Checking change permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'teacher'

    def has_delete_permission(self, request, obj=None):
        print(f"Checking delete permission for {request.user.username} with role {request.user.role}")
        return request.user.is_superuser or request.user.role == 'teacher'

models.py:

from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    ROLE_CHOICES = [
        ('director', 'director'),
        ('teacher', 'teacher'),
        ('student', 'student'),
    ]
    role = models.CharField(max_length=10, choices=ROLE_CHOICES)

class Group1(models.Model):
    name = models.CharField(max_length=100)
    student = models.ManyToManyField('Student', related_name='groups')
    teacher = models.ForeignKey('CustomUser', limit_choices_to={'role': 'teacher'}, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class Student(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    patronymic = models.CharField(max_length=100)
    user = models.OneToOneField(CustomUser, limit_choices_to={'role': 'student'}, on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.first_name} {self.last_name} {self.patronymic}"

class Subject(models.Model):
    name = models.CharField(max_length=100)
    teacher = models.ForeignKey(CustomUser, limit_choices_to={'role': 'teacher'}, on_delete=models.CASCADE)
    groups = models.ManyToManyField(Group1, related_name='subjects')

    def __str__(self):
        return self.name

class Grade(models.Model):
    student = models.ForeignKey(Student, on_delete=models.CASCADE)
    subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
    grade = models.IntegerField()

    def __str__(self):
        return f"{self.student} - {self.subject} - {self.grade}"

formsAdmin.py:

from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):
    class Meta:
        model = CustomUser
        fields = ('username', 'role', 'password1', 'password2')
    
    #enable staff and active statuses for created user for admin panel
    def save(self, commit=True):
        user = super().save(commit=False)
        user.is_staff = True
        user.is_active = True
        if commit:
            user.save()
        return user

class CustomUserChangeForm(UserChangeForm):
    class Meta:
        model = CustomUser
        fields = ('username', 'first_name', 'last_name', 'email', 'role', 'is_staff', 'is_active', 'is_superuser')

settings.py:

AUTH_USER_MODEL = 'school.CustomUser'
AUTH_PASSWORD_VALIDATORS = [
    # {
    #     'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    # },
    # {
    #     'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    # },
    # {
    #     'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    # },
    # {
    #     'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    # },
]

Welcome @dtstimdjumaniyazov !

Side Note: When posting code here, enclose the code between lines of three
backtick - ` characters. This means you’ll have a line of ```, then your code,
then another line of ```. This forces the forum software to keep your code
properly formatted. (I have taken the liberty of correcting your original posts.
Please remember to do this in the future.)

Please provide more details about the issue you’re trying to solve here. Describe what is happening that you are not expecting to see happen, or what is not happening that you are expecting to see. Be specific about the symptoms you are seeing. If you’re getting some kind of error message, please post the complete error message and the traceback (if any) from your server console. (Do not post screen images of errors you see being reported in the browser.)

1 Like

Couple points here -

The admin’s recommended use is limited to an organization’s internal management tool. It’s not intended for building your entire front end around.

  • If you’re going to use the admin like you’re describing, then what you really want to do is work with Django’s built-in permission system, not try to work around it.
    What this means in principle is that instead of creating these “roles” as you have, you create Django groups for those roles, and assign the predefined permissions to those groups. This allows the admin to check permissions as it is designed, and avoiding the need for you to override all those permission methods.

  • Also see ModelAdmin.has_module_permission

1 Like

Thank you very much, @KenWhitesell! :pray: