Добавьте аннотацию ко всем запросам 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
в качестве поля пользователя и попытаться убедиться, что оно всегда актуально, но я специально пытаюсь не добавлять эти денормализованные данные в базу данных.