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?
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.