Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Django ORM Basic ORM Usage Exclusivity

Greg Kaleka
Greg Kaleka
39,021 Points

Complex query and ordering results in Django

I've updated the search view function to return matches on both title and description:

def search(request):
    term = request.GET.get('q')
    courses = models.Course.objects.filter(
        Q(title__icontains=term) | Q(description__icontains=term)
    )
    return render(request, 'courses/course_list.html', {'courses': courses})

This works, but I'd like to order the results so that courses with titles that contain the search term show up first, followed by those where titles do not contain the search term but the description does.

I tried creating two queries and unioning them like so:

good_matches = models.Course.objects.filter(
        Q(title__icontains=term))
just_ok_matches = models.Course.objects.filter(
        ~Q(title__icontains=term) & Q(description__icontains=term)
    )
courses = good_matches | just_ok_matches

But the order seems to be unchanged from the first example.

This SO answer seems to cover how to do this with raw SQL, by creating a scoring system. Perhaps there's a way to implement this with Django's ORM?

I could create the two queries as above and pass them both to the view like so:

def search(request):
    term = request.GET.get('q')
    good_matches = models.Course.objects.filter(
        Q(title__icontains=term))
    just_ok_matches = models.Course.objects.filter(
        ~Q(title__icontains=term) & Q(description__icontains=term)
    )
    return render(request, 'courses/course_list.html', {'courses': good_matches, 'other_courses': just_ok_matches})

and then edit course_list.html to show courses and then other_courses, but that feels a bit janky to me.

Any ideas would be appreciated!

Cheers :beers:

-Greg