2

What would be the best way to check model type of an account that has extended Django User model? I have two types of User accounts (students and teachers, let say) that extend django User model:

class Student(models.Model):
     student_bd = models.CharField(max_length=50)
     student_user = models.ForeignKey(User)
     ...

class Teacher(models.Model):
     teacher_bd = models.CharField(max_length=50)
     teacher_user = models.ForeignKey(User)
     ...

So, how can i know if request.user is Student or Teacher?

Ljubisa Livac
  • 819
  • 3
  • 13
  • 38

2 Answers2

3

There is no data about the Student and Teacher models saved in the User table, so you'll have to query for the related object.

If you don't need the actual profile (Student or Teacher object), the fastest way is to use the exists() function on the related set:

if request.user.student_set.exists():
    # student
elif request.user.teacher_set.exists():
    # teacher

If you know you're going to need the profile object later on, it would be faster to fetch the results and check for an existing object in Python:

if request.user.student_set.all():
    # do something with student_set
elif request.user.teacher_set.all():
    # do something with teacher_set

Side note: If your user shouldn't ever have more than one Student or Teacher object related, it might be a better idea to use a OneToOneField instead of a ForeignKey. That way, you don't have to bother with all() etc, but you can just access the related model instance with user.student or user.teacher. This will also allow you to use select_related, so that both the user object and the student or teacher object are fetched in a single query.

knbk
  • 52,111
  • 9
  • 124
  • 122
  • Kudos, didn't know you can go through related objects that way. Makes my answer look... rudimentary. +1 from me. – Eduard Luca Jun 19 '14 at 12:36
  • @knbk, thank you for your thorough answer, and for side note. Eduardo answered first so i have to accept his answer as correct. BTW, i don't know why but Django says that `'User' object has no attribute 'student_set'`. – Ljubisa Livac Jun 19 '14 at 12:46
  • @LjubisaLivac Which version of Django are you using? The default name could be different, but you can always specify a related name: `student_user = models.ForeignKey(User, related_name='students')`. I always specify a related name, as it avoids a lot of confusion. – knbk Jun 19 '14 at 12:52
2

If you have a User model and want to check if that model corresponds to either a Teacher or a Student model, you will need to get the corresponding row from each the tables:

try:
    Student.objects.get(student_user=request.user)
    is_student = True
except Student.DoesNotExist:
    is_student = False

And the same for the teacher. is_student and is_teacher will tell you if the User is a Student or a Teacher respectively. This will also work in the odd case if a user is both a student and a teacher :) Not useful in this case, but thought it'd help with other roles in a school.

Eduard Luca
  • 6,514
  • 16
  • 85
  • 137
  • And before you ask, no, there's no way to do that without querying the DB. – Eduard Luca Jun 19 '14 at 12:19
  • Thank you for your answer, you've helped me. This is what i've done: `Student.objects.filter(student_id=user.id).first()` - it returns object or None. – Ljubisa Livac Jun 19 '14 at 12:41
  • @LjubisaLivac please revise your code, because it will produce wrong results. You can do it your way, but with a small change: `Student.objects.filter(student__student_user_id=user.id).first()`. What you are doing is to compare the student ID with the user ID, which is not what you want. The revised code above compares the (request) user ID with the student's user ID. – Eduard Luca Jun 19 '14 at 13:51
  • Yeah, you're right, i didn't notice that! Thank you again – Ljubisa Livac Jun 20 '14 at 06:44