Поисковая система при помощи Django ORM

Помогите, пожалуйста, решить задание.

Есть модель Джанго Post:

class Post(models.Model):
    text = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='posts'
    )
    group = models.ForeignKey(
        Group,
        on_delete=models.SET_NULL,
        max_length=200,
        blank=True,
        null=True,
        related_name='posts')

А это само задание: "Допишите код view-функции: она должна вывести на главную страницу посты, в которых есть запрошенное ключевое слово. Форма отправляет запрос методом GET. Запрос сделайте так, чтобы при обращении к свойствам модели author и group не порождались дополнительные запросы к базе." Код из файла со вьюшкой:

from django.shortcuts import render

from .models import Post, User


def index(request):
    keyword = request.GET.get("q", None)
    if keyword:
        posts = ...
    else:
        posts = None

    return render(request, "index.html", {"posts": posts, "keyword": keyword})

В переменной posts нужно написать запрос в БД. Все, на что меня хватило, это: posts = Post.objects.filter(text__contains='keyword '). Но я не понимаю, как дальше построить запрос, чтобы при поиске выводился не только текст поста, но и поля author и group.


Ответы (2 шт):

Автор решения: Andrey Maslov

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

posts = Post.objects.filter(
    Q(text__icontains=keyword) | 
    Q(author__fio__icontains=keyword) |
    Q(group__name__icontains=keyword)
)

только нужно вместо fio подставить поле из модели авторов, а вместо name название группы.

Подробней о Q - https://docs.djangoproject.com/en/3.2/ref/models/querysets/#q-objects

→ Ссылка
Автор решения: Александр Лапин

У меня вот такой код прошёл:

def index(request):
    keyword = request.GET.get("q", None)
    if keyword:
        posts = Post.objects.filter(text__contains=keyword).select_related('author', 'group')
    else:
        posts = None

    return render(request, "index.html", {"posts": posts, "keyword": keyword})
→ Ссылка