Search code examples
djangodjango-modelsdjango-authentication

Get concrete profile from request.user in Django


I have abstract profile linked to the User:

class Account(models.Model):
   class Meta:
        abstract = True

    user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True)
    patronic_name = models.CharField(max_length=255, default="")
    # additional fields and methods
    def foo(self):
       print('account')

And I have multiple different roles and implementations - student, tutors, admins, etc. I created a class for each of them, derived from the Account class.

class Teacher(Account):
    def foo(self):
        print('teacher')
    # ...additional fields and methods

class Student(Account):
        def foo(self):
            print('student')
    # ...additional fields and methods

Now I want to call foo method on the class object, like this:

@login_required
def index(request):
   request.user.account.foo()

But since Account class is abstract, there is no request.user.account M2M relationship. I have request.user.student, request.user.teacher relationships, but I do not know the type of relationship.

Is there any way to get the concrete account of request.user User object?


Solution

  • You could add a property to your User model that inspects every subclass of Account and returns the first subclass that has a relationship to the user.

    Something like this should work

    @property
    def account(self):
        for subclass in Account.__subclasses__():
            try:
                return getattr(self, subclass.__name__.lower())
            except DoesNotExist:
                continue