Как осуществлять поиск и фильтрацию по нескольким связанным моделям?

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

Структура модели:

    Institutions:
     - Name
     - Id
     - email
     - address
    ...... etc.

    Courses:
     - owner = models.ForeignKey(Institution, on_delete=models.CASCADE)
     - name
     - ref
     - license
     - overview

..... etc

Теперь, используя все вышесказанное, я создал строку поиска, в которой пользователю нужно что-то ввести, а затем нажать кнопку "поиск" или клавишу "Enter". Это покажет результаты поиска. Мой код поиска:

query = request.GET.get('q')
courses = Course.objects.filter(name__icontains=query)
institution= Institution.objects.filter(name__icontains=query)

queryset_chain = chain(courses,institution)

Проблема заключается в том, что я хочу отобразить результат следующим образом.

сценарий 1:

Допустим, что курс и институт имеют одинаковые названия, например, "tech".

Когда пользователь ищет "tech", мне нужно показать результат следующим образом:


Название учреждения

  • Название курса

сценарий 2:

Допустим, что курс имеет название "техник", но не институт имеет такое название.

Когда пользователь ищет "tech", мне нужно показать результат следующим образом: В этом случае мне нужно показать название курса, а также соответствующее учебное заведение название:


Название учреждения

  • Название курса

сценарий 3:

где институт имеет название "техник". Но нет курса название.


Название учреждения

  • любое произвольное имя курса

Как работать с таким видом объединенного поиска и фильтра?

Поскольку я не могу воспроизвести ваше приложение, я могу только дать вам представление о том, как решить эту проблему. Модель Course является дочерней по отношению к модели Institution, вы можете применить prefetch_related() или select_related() для предотвращения N+1 запросов. Эти коды обобщают все три сценария, используя объект Q() из Django, поскольку вы можете использовать выражение OR -> | на нем.

from django.db.models import Q

query = request.GET.get('q')
courses = Course.objects.prefetch_related('institution') \
                        .filter(Q(institution_set__name__icontains=query) |
                                Q(course_set__name__icontains=query))

Вам также не нужно использовать chain, попробуйте regroup. Я не уверен, какого результата вы ожидаете от третьего сценария, но, возможно, добавление условия пойдет на пользу.

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