christine11
christine11

Reputation: 61

How to search and filter on multiple related models?

I am creating an search and filter system in which user can type and search related courses and institutions. This is my model structure:

Model Structure:

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

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

..... etc

Now by using the above, i have created a search bar in which user needs to type something and then press "search" button or else press "Enter" key. This will show search results. My search code:

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

queryset_chain = chain(courses,institution)

So the problem here is that, I want to display the result as follows.

scenario 1:

Lets say that course and Institution has same name like "tech".

When user search for "tech", I need to show result as follows:


Institution Name


scenario 2:

Lets say that course has name as "tech" but not Institution has that name.

When user search for "tech", I need to show result as follows: In this case, I need to show the Course name and also correspondant Institution name:


Institution Name


scenario 3:

where Institution has "tech" as name. But no course name.


Institution Name


How to handle this kind of clubbed search and filter ?

Upvotes: 2

Views: 77

Answers (1)

Coderio
Coderio

Reputation: 442

Since I cannot replicate your app, I can only give you an idea of how to solve this. Course model is the child of the Institution model, you can apply prefetch_related() or select_related() to prevent N+1 queries. These codes sum up all three scenarios using the Q() object from Django since you can use the OR -> | expression on it.

from django.db.models import Q

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

You also don't need to use chain, try regroup. I'm not sure what result you expect for the third scenario, but maybe adding the condition will do good.

Upvotes: 1

Related Questions