djangodjango-modelsdjango-viewsdjango-permissions

Allow Admin user to see only the user the admin creates in Django


I am trying to create a school management system, where by a school can register and becomes an admin, the school which is an admin, can create their staffs and students. The staff and students should be able to login to their accounts. The key thing here is that, there will be more than one school registered, thus each school should only see their own staffs and students.

How can i ensure that the admin only sees the students and staff account created by that admin alone?

Functionality so far I have created different user type accounts, admin(school) can login and create a student and staff accounts, students and staffs account created by admin which is the school can also login.

The thing here is that, all admin can see all staffs, i don't want this to happen, i want admin to only see the student and staffs created by that admin alone.

Below is my code for review

accounts/models.py my custom user model

class CustomUser(AbstractUser):
    USER_TYPE = ((1, "school"), (2, "Staff"), (3, "Student"))
    GENDER = [("M", "Male"), ("F", "Female")]

    username = None  # Removed username, using email instead
    email = models.EmailField(unique=True)
    user_type = models.CharField(default=1, choices=USER_TYPE, max_length=1)
    gender = models.CharField(max_length=1, choices=GENDER)
    address = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []
    objects = CustomUserManager()

    def __str__(self):
        return self.last_name + ", " + self.first_name


# The School
class Admin(models.Model):
    admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE)

    def __str__(self):
        return str(self.admin.email)

# staff
class Staff(models.Model):
    admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
    def __str__(self):
        return str(self.admin.email)



# students
class Student(models.Model):
    admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
    def __str__(self):
        return str(self.admin.email)

Views that allows the school to add staffs and students school/views.py


def add_staff(request):
    form = StaffForm(request.POST or None, request.FILES or None)
    context = {'form': form, 'page_title': 'Add  Staff'}
    if request.method == 'POST':
        if form.is_valid():
            first_name = form.cleaned_data.get('first_name')
            last_name = form.cleaned_data.get('last_name')
            address = form.cleaned_data.get('address')
            email = form.cleaned_data.get('email')
            gender = form.cleaned_data.get('gender')
            password = form.cleaned_data.get('password')
        
            try:
                user = CustomUser.objects.create_user(
                    email=email, password=password, user_type=2, first_name=first_name, last_name=last_name)
                user.gender = gender
                user.address = address
                user.save()
                messages.success(request, " Staff Successfully Added")
                return redirect('school_home')

            except Exception as e:
                messages.error(request, "Could Not Add " + str(e))
        else:
            messages.error(request, "Please fulfil all requirements")

    return render(request, 'add_staff_template.html', context)


def add_student(request):
    form = StudentForm(request.POST or None, request.FILES or None)
    context = {'form': form, 'page_title': 'Add  Student'}
    if request.method == 'POST':
        if form.is_valid():
            first_name = form.cleaned_data.get('first_name')
            last_name = form.cleaned_data.get('last_name')
            address = form.cleaned_data.get('address')
            email = form.cleaned_data.get('email')
            gender = form.cleaned_data.get('gender')
            password = form.cleaned_data.get('password')
        
            try:
                user = CustomUser.objects.create_user(
                    email=email, password=password, user_type=3, first_name=first_name, last_name=last_name)
                user.gender = gender
                user.address = address
                user.save()
                messages.success(request, " Student Successfully Added")
                return redirect('school_home')

            except Exception as e:
                messages.error(request, "Could Not Add " + str(e))
        else:
            messages.error(request, "Please fulfil all requirements")

    return render(request, 'add_student_template.html', context)

the views that displays the created staffs and students


def school_home (request):
    total_staff = Staff.objects.all().count()
    total_students = Student.objects.all().count()
    # listing the students and staffs
    students = CustomUser.objects.filter(user_type=3)
    staffs = CustomUser.objects.filter(user_type=2)


    
    context = {
        'total_staff': total_staff,
        'total_students': total_students,  
        'students': students,      
        'staffs': staffs,       

    }
    return render(request, 'school_home.html', context)


My question is How do i make it possible that only the students and staffs created by a school is visible to the school. i don't know the best approach to use to make it work.


Solution

  • I found a way around the question To ensure that a school sees only their staffs and student add this code to the existing code in the question

    my custom user model** add to existing code

    accounts/models.py

    class CustomUser(AbstractUser):
        created_by = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL)
    

    Views that allows the school to add staffs and students

    school/views.py

    def add_student(request):
        form = StudentForm(request.POST or None, request.FILES or None)
        context = {'form': form, 'page_title': 'Add  Student'}
        if request.method == 'POST':
            if form.is_valid():
                first_name = form.cleaned_data.get('first_name')
                last_name = form.cleaned_data.get('last_name')
                address = form.cleaned_data.get('address')
                email = form.cleaned_data.get('email')
                gender = form.cleaned_data.get('gender')
                password = form.cleaned_data.get('password')
            
                try:
                    user = CustomUser.objects.create_user(
                        email=email, password=password, user_type=3, first_name=first_name, last_name=last_name)
                    user.gender = gender
                    user.address = address      
                    user.created_by = request.user
                    user.save()
                    messages.success(request, " Student Successfully Added")
                    return redirect('school_home')
    
                except Exception as e:
                    messages.error(request, "Could Not Add " + str(e))
            else:
                messages.error(request, "Please fulfil all requirements")
    
        return render(request, 'add_student_template.html', context)
    

    in the views.py above notice the created_by that points to the current user, repeat the same method for the staff views

    the views that displays the created staffs and students

        def school_home (request):
            total_staff = CustomUser.objects.filter(user_type=2, created_by=request.user).count()
            total_student = CustomUser.objects.filter(user_type=3, crea
    ted_by=request.user).count()
            # listing the students and staffs
            students = CustomUser.objects.filter(user_type=3, created_by=request.user)
            staffs = CustomUser.objects.filter(user_type=2, created_by=request.user)
           
            context = {
                'total_staff': total_staff,
                'total_students': total_students,  
                'students': students,      
                'staffs': staffs,       
        
            }
            return render(request, 'school_home.html', context)