How to go 2 layers deep reverse relations inside django models?

I'm using a single User model for authentication and creating multiple "type" accounts using the User model. Every type has a different dashboard so different things to show.

Organization
-> Teacher
    -> Student

Q - I want to list the teachers and their corresponding students when inside a organization account ? It is a listView so I want to know how would I use revere relations to list all the students under specific teachers from an Organization account ?

class User(AbstractUser):
    ...


class Organization(models.Model):
    user_id = models.OneToOneField(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='superAdmin')
    ...

class Teacher(models.Model):
    user_id = models.OneToOneField(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='faculty')
    super_admin_id = models.ForeignKey(
        SuperAdmin, on_delete=models.CASCADE, related_name='faculty')
    ...


class Student(models.Model):
    user_id = models.OneToOneField(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='user')
    faculty_id = models.ForeignKey(
        Teacher, on_delete=models.CASCADE, related_name='student')
    ...

If there's any advice on how I can improve the existing model schema, I'd like to know that as well.

1 answer

  • answered 2021-09-12 09:29 BrianD

    You can fetch the teachers along with their students (in two db hits) like this:

    teachers = Teacher.objects.filter(
        user_id__superAdmin=request.user.superAdmin
    ).prefetch_related('student')
    
    for teacher in teachers:
        print(f'Teacher: {teacher.pk}')
        for student in teacher.student.all():
            print(f'Student: {student.pk}')
    

    EDIT:

    You can also annotate per teacher the number of students assigned to them so:

    teachers = Teacher.objects.filter(
        user_id__superAdmin=request.user.superAdmin
    ).annotate(num_students=Count('student'))
    
    for teacher in teachers:
        print(f'Teacher {teacher.pk} has {teacher.num_students} students')
    

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum