11

So I have a model called Puzzle which contains a title, question, and a subject. I want to be able to search for puzzles by entering a string. My search bar also contains three checkboxes: - title - question - subject

I want to somehow be able to query my database to see if the ticked fields contain the search text. For example, if title and question were ticked, I would query to see if the puzzle's title contains this string OR its questions contains the string. Is there any way to query this in Django?

I know that if I wanted to check just one of these fields, for instance the title, I could just do this:

Puzzle.objects.filter(title__contains=search_text)

But I want to be able to dynamically query the fields that are ticked.

Currently, my view contains three boolean values: title, question, and subject. The boolean is True is it is ticked, and false if it is not ticked.

How can I manipulate these three booleans along with Django queries to be able to dynamically query my database?

Thank you

1 Answer 1

24

You can do OR queries using Q objects:

from django.db.models import Q

Puzzle.objects.filter(
    Q(title__contains=search_text) |
    Q(question__contains=search_text) |
    Q(subject__contains=search_text)
)

Of course you can build this Q object dynamically:

q = Q()
if title:
    q |= Q(title__contains=search_text)
if question:
    q |= Q(question__contains=search_text)
if subject:
    q |= Q(subject__contains=search_text)

# If you want no result if none of the fields is selected
if q:
    queryset = Puzzle.objects.filter(q)
else:
    queryset = Puzzle.objects.none()

# Or if you want all results if none of the fields is selected
queryset = Puzzle.objects.filter(q)

If you have all selected fields in a list (ie. search_fields = ['title', 'subject'], you can even make it more generic:

from functools import reduce
from operators import or_

q = reduce(or_, [Q(**{f'{f}__contains': search_text}) for f in search_fields], Q())
Puzzle.objects.filter(q)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.