Django - Конкатенация двух полей в отношении "многие ко многим" для поиска строки

Я использую Django 3.2.6 и Mysql.

У меня есть две модели

class Author(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

class Book(models.Model):

...
author = models.ManyToManyField(Author, related_name="authors")

Книга может иметь несколько авторов, а автор может иметь несколько книг. Теперь я хочу написать простой поиск, в котором пользователи должны иметь возможность искать по имени автора.

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

def search(self, keyword):
        return (
            self
                .filter(
                Q(title__icontains=keyword)
                | Q(description__icontains=keyword)
                | Q(isbn__icontains=keyword)
                | Q(category__name__icontains=keyword)
                | Q(author__first_name__icontains=keyword)
                | Q(author__last_name__icontains=keyword)
            )
            .annotate(book_count=Count("id"))
            .order_by("-id")
    )

Обратите внимание, что annotate(book_count=Count("id")) эта часть важна, иначе она вернет дублирующиеся строки, если у книги несколько авторов.

Это работает, если я ищу только по имени_фамилии или фамилии. Например, он вернет результаты, если я буду искать "John" или "Smith". Но если я буду искать полное имя, например "Джон Смит", это не даст никаких результатов.

После поиска я изменил функцию следующим образом

def search(self, keyword):
        return (
            self
                .annotate(
                    full_name=Concat(
                    "author__first_name", Value(" "), "author__last_name",
                    output_filed=CharField()
                ))
                .filter(
                Q(title__icontains=keyword)
                | Q(description__icontains=keyword)
                | Q(isbn__icontains=keyword)
                | Q(category__name__icontains=keyword)
                | Q(author__first_name__icontains=keyword)
                | Q(author__last_name__icontains=keyword)
                | Q(full_name__icontains=keyword)
            )
            .annotate(book_count=Count("id"))
            .order_by("-id")
        )

Но теперь я получаю следующую ошибку

SELECT list is not in GROUP BY clause and contains nonaggregated column 'author.first_name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by")

Как я могу решить эту проблему? Правильный ли это подход? Я могу получить нужные результаты, используя необработанный запрос. Но можно ли это реализовать в django-way.

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