Поиск пользователя по составному ФИО

Аннотируйте полное имя через Concat и Coalesce, уберите крайние пробелы через Trim, затем фильтруйте по нормализованной строке.

Короткий ответ

Что ответить на собеседовании

Аннотируйте полное имя через Concat и Coalesce, уберите крайние пробелы через Trim, затем фильтруйте по нормализованной строке.

Подробный разбор

Ответ с пояснениями

Условие

Сформировать запрос в Django ORM, который осуществит поиск записи пользователя, используя полное ФИО, сформированное из полей last_name, first_name и middle_name.

class User(models.Model):
    last_name = models.CharField('Фамилия', max_length=128)
    first_name = models.CharField('Имя', max_length=128)
    middle_name = models.CharField('Отчество', max_length=128, blank=True, null=True)

class Employee(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

Ответ

Аннотируйте полное имя через Concat и Coalesce, уберите крайние пробелы через Trim, затем фильтруйте по нормализованной строке.

from django.db.models import Value, CharField
from django.db.models.functions import Concat, Coalesce, Trim

full_name = ' '.join(input_name.split())
users = User.objects.annotate(
    full_name=Trim(Concat(
        'last_name', Value(' '), 'first_name', Value(' '),
        Coalesce('middle_name', Value('')),
        output_field=CharField(),
    ))
).filter(full_name=full_name)

Coalesce обрабатывает отсутствующее отчество, а Trim убирает последний пробел. Предполагается, что отдельные поля при записи уже очищены от лишних пробелов. ФИО не гарантирует уникальность, поэтому filter безопаснее безусловного get. Для поиска по Employee используйте пути user__last_name и аналогичные. На больших таблицах вычисляемая конкатенация может потребовать отдельного поискового индекса.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее