Добавьте аннотацию ко всем запросам Django ORM, которые проходят через модель

У Django AbstractUser есть поля для first_name и last_name, а также метод get_full_name.

Если я хочу фильтровать пользователей на основе поиска по их полному имени, я могу добавить пользовательский менеджер моделей для пользователя, который имеет метод, подобный следующему:

def filter(self, *args, **kwargs):
    queryset = super().get_queryset()
    if any(key for key in kwargs if key.startswith('full_name')):
        queryset = queryset.annotate(
            full_name=Concat(models.F('first_name'), models.Value(' '), models.F('last_name'))
        )
    return queryset.filter(*args, **kwargs)

Означает, что я могу делать такие вещи, как:

User.objects.filter(full_name='Foo Bar')
User.objects.filter(full_name__icontains='foo b')
... etc

Но, конечно, это будет работать только при прямой фильтрации Пользователей выше. Если у вас есть объекты Post, которые привязаны к пользователю, то вы получите следующее:

Post.objects.filter(user__full_name='Foo Bar')
...
FieldError: Related Field got invalid lookup: full_name

Вопрос в том, есть ли способ (без модификации всех моделей, чтобы иметь пользовательские менеджеры), чтобы Django всегда распознавал заданный термин (в данном случае 'full_name') во всех соединениях с таблицей данной модели, и аннотировал необходимое значение, чтобы его можно было фильтровать по?

Примечание: я знаю, что я, конечно, могу добавить full_name в качестве поля пользователя и попытаться убедиться, что оно всегда актуально, но я специально пытаюсь не добавлять эти денормализованные данные в базу данных.

Вернуться на верх