djangodjango-modelsdjango-querysetdjango-annotatedjango-managers

Manager's annotations don't show up when traversing ForeignKey


Suppose I have such classes:

class UserManager(Manager):
    def get_queryset(self):
        return super().get_queryset().annotate(
            full_name=Concat(
                F('first_name'), Value(' '), F('last_name'),
                output_field=CharField()
            )
        )


class User(Model):
    first_name = CharField(max_length=16)
    last_name = CharField(max_length=16)

    objects = UserManager()


class Profile(Model):
    user = ForeignKey(User, CASCADE, related_name='profiles')

And I want to include an annotated field in my query:

Profile.objects.filter(GreaterThan(F('user__full_name'), Value(24)))

But I got a FieldError: Cannot resolve keyword 'full_name' into field. Choices are: first_name, id, last_name, profiles

It's clear that I could repeat my annotation in a current query:

Profile.objects.filter(GreaterThan(Concat(F("user__first_name"), Value(" "), F("user__last_name"), output_field=CharField(),), Value(24)))

But as soon as my annotations will become more complex, my code become mess. Is there any workaround?


Solution

  • I overcomplicated my problem. I can filter users then retrieve profiles according to foreign keys:

    users = User.objects.filter(GreaterThan(F('full_name'), Value(24)))
    users_pk = users.values_list('pk', flat=True)
    Profile.objects.filter(user__pk__in=users_pk).all()
    

    We use .values_list() to return only specified fields' values, in this case - primary keys. Parameter flat returns single value, instead of tuples.