Search code examples
djangodjango-querysetdjango-filtersearchbardjango-q

How to filter by boolean field in search bar - django


I'm working on a Django project that is a project management system. Basically in the navbar, I've implemented a searcher to search for specific projects like the title, the client, the description, etc.

I'd like to give them the possibility of searching also the projects that are urgent (urgent in my Project model is a boolean field), but the way I implemented it doesn't work.

This is my Project Model:

class Project(models.Model):
    title = models.CharField(max_length=255)
    description = models.CharField(max_length=1000)
    client = models.ForeignKey(Cliente, on_delete=models.CASCADE)
    complete = models.BooleanField(default=False)
    urgent = models.BooleanField(default=False)
    deadline = models.DateField()
    ...

To make the search bar (that in my html file is:)

<form method="get" class="form-inline">
  <input class="form-control mr-sm-2" name="q" id="id_q" type="text" placeholder="Search..." aria-label="Search" value="{{query}}">

  <button class="btn btn-outline-dark my-2 my-sm-0" type="submit">
      <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-search" fill="currentColor"
           xmlns="http://www.w3.org/2000/svg">
          <path fill-rule="evenodd"
                d="M10.442 10.442a1 1 0 0 1 1.415 0l3.85 3.85a1 1 0 0 1-1.414 1.415l-3.85-3.85a1 1 0 0 1 0-1.415z"/>
          <path fill-rule="evenodd"
                d="M6.5 12a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zM13 6.5a6.5 6.5 0 1 1-13 0 6.5 6.5 0 0 1 13 0z"/>
      </svg>
  </button>
</form>

How I've implemented this function:

def get_projects_qs(proj, query=None):
    queryset = []
    queries = query.split(" ")

    for q in queries:

        projects = proj.filter( Q(title__icontains=q) | Q(description__icontains=q) | Q(urgent__icontains=q) | Q(client__client__icontains=q) ).distinct()

        for project in projects:
            queryset.append(project)

    return list(set(queryset))

Now, if I do Q(urgent_icontains=q) it doesn't work, but if I do Q(urgent=q) it works only the first time and then I get this error:

ValidationError at /marketing/
['“” value must be either True or False.']

Solution

  • let's assume we have a model like this:

    class Project(models.Model):
        title = models.CharField(max_length=255)
        complete = models.BooleanField(default=False)
        urgent = models.BooleanField(default=False)
        .
        .
        .
    

    views.py:

    from . models import Product
    
    
    def is_valid_queryparam(param):
        return param != '' and param is not None
    
    
    def search(request):
        queryset = Product.objects.all()
    
        search = request.GET.get('search')
        complete = request.GET.get('complete')
        urgent = request.GET.get('urgent')
    
    
        if is_valid_queryparam(search):
            queryset = queryset.filter(title__icontains=search)
    
        if is_valid_queryparam(complete):
            queryset = queryset.filter(complete=True)
    
        elif is_valid_queryparam(urgent):
            queryset = queryset.filter(urgent=True)
    
        context = {
            'queryset': queryset
        }
    
        return render(request, 'search.html', context)
    

    now in template ( search.html ):

    <form id="mySearch" method="GET">
        <input type="search" name="search" placeholder="Search..." />
        <button" type="submit">Click to Search</button>
    
        <input type="checkbox" name="complete" id="checkbox-1" onchange="$('#mySearch').submit();" {% if request.GET.complete == 'on' %} checked {% endif %}>
        <label for="checkbox-1">complete</label>
    
        <input type="checkbox" name="urgent" id="checkbox-2" onchange="$('#mySearch').submit();" {% if request.GET.urgent == 'on' %} checked {% endif %}>
        <label for="checkbox-2">urgent</label>
    </form>