Search code examples
pythondjangodjango-querysetdjango-q

Django : Get queryset with filters over list (filled and/or empty)


I'm working on a module which let to display objects thanks to filters defined by users.

View.py file :

search_category = Document.objects.values_list('publication__category__name', flat=True).distinct()
kwargs['search_category'] = search_category

search_format = Document.objects.values_list('format', flat=True).distinct()
kwargs['search_format'] = search_format

search_language = Document.objects.values_list('language', flat=True).distinct()
kwargs['search_language'] = search_language

checkbox_category = self.request.GET.getlist('CategoryChoice')
checkbox_format = self.request.GET.getlist('FormatChoice')
checkbox_language = self.request.GET.getlist('LanguageChoice')
choice_title = self.request.GET.get('TitleChoice')

test_research = Document.objects\
            .filter(Q(publication__category__name__isnull=True) | Q(publication__category__name__in=checkbox_category))\
            .filter(Q(format__isnull=True) | Q(format__in=checkbox_format))\
            .filter(Q(language__isnull=True) | Q(language__in=checkbox_language))\
            .filter(Q(title__isnull=True) | Q(title__in=choice_title))

My template file for one filter (language) :

<button class="btn btn-default btn-choice" type="button" data-toggle="collapse" data-target="#language"
                aria-expanded="false" aria-controls="language"><span
          class="glyphicon glyphicon-chevron-down"></span> {% trans 'Language' %}</button>
        <div class="row">
          <div class="col">
            <div class="collapse multi-collapse" id="language">
              <div class="card card-body card-choice">
                {% for language in search_language %}
                  <input type="checkbox" class="fakeRadio" name="LanguageChoice" value="{{ language }}">
                  {{ language }}<br>
                {% endfor %}
              </div>
            </div>
          </div>
        </div>

It looks like this in my web application :

enter image description here

I can check one or multiple checkboxes, but also none checkbox for a specific criteria. This last option makes issue, because, for example, if I don't check language, the resulting queryset is empty and shouldn't be because it should take account the others filters.

Example :

Object 1 : Category = 'FOOD_CONTACT', Format = 'pdf', Language = 'FR', Title = 'This is my first title'
Object 2 : Category = 'FOOD_CONTACT', Format = 'epub', Language = 'EN', Title = 'This is my second title'
Object 3 : Category = 'OTHER', Format = 'pdf', Language = 'FR', Title = 'ZZ'

Now, if I check this :

Category filter : ['FOOD CONTACT']
Format filter : []
Language filter : []
Title filter : 
It should return : Object 1, Object 2

Category filter : ['FOOD CONTACT']
Format filter : ['pdf']
Language filter : []
Title filter : 
It should return : Object 1

Category filter : []
Format filter : ['pdf']
Language filter : []
Title filter : 'Z'
It should return : Object 3

Solution

  • I think the solution is to build your filters dynamically, and just don't include any filters that the user didn't ask for.

    # default to all documents
    test_research = Document.objects.all()
    
    # if user entered any search criteria, add those filters
    if category:
        test_research = test_research.filter(publication__category__name__in=category)
    
    if format:
        test_research = test_research.filter(format__in=format)
    
    if language:
        test_research = test_research.filter(language__in=language)
    
    if title:
        test_research = test_research.filter(title__icontains=title)