Question

I have two apps, "account" and "myapp". I'm trying to display in a view only those teacher objects which belong to the same organisation as the request.user.

account/models.py
from django.contrib.auth.models import User

class Organisation(models.Model):
    name = models.CharField(max_length=100, unique=True)
    is_active = models.BooleanField(default=True)

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True)
    organisation = models.ForeignKey(Organisation, editable=False)
    is_organisationadmin = models.BooleanField(default=False)

User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])

Note the last line, from this blog post, which enables accessing user profile information by something like user.profile.organisation

myapp/models.py
from django.contrib.auth.models import User

class Teacher(models.Model):
    user = models.OneToOneField(User, related_name='teacher')
myapp/views.py
from myproject.account.models import Organisation, UserProfile
from myproject.myapp.models import Teacher
from django.contrib.auth.models import User

def homepage(request):
    if request.user.is_authenticated():
        teachers = Teacher.objects.filter(user.profile.organisation == request.user.profile.organisation, user__is_active = True)

I get "NameError at /homepage/, global name 'user' is not defined". I think this is because I'm not correctly accessing the teacher.user property of each Teacher object, but I could be wrong.

I've tried all sorts of combinations of reverse traversing the relationship:

user.is_active
user__is_active
user.profile.organisation
user.profile__organisation

but many of the above give me "SyntaxError at /homepage/ keyword can't be an expression", so I think the current incarnation is roughly right.

Oddly, the right hand side of the filter seems to work fine (the = request.user.profile.organisation part)

Was it helpful?

Solution

The documentation on query lookups that span relationships is pretty informative. The thing to realize is that it's a standard function, so the left-hand side must always be a single keyword, not an expression. To enable this, use the double-underscore syntax:

Teacher.objects.filter(user__profile__organisation=request.user.profile.organisation, user__is_active = True)

Also note it's a single = - again, it's a function invocation, not an expression.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top