Search code examples
pythondjangodjango-filter

Django-Filter: Creating checkboxes for Boolean Field


Models.py

class Task(models.Model):
    online = models.BooleanField(blank=False)

I would like to use django-filter to create the following checkboxes in the form:

[] Online [] Physical

If form is empty or both are ticked, get Task.objects.all(). If only one is ticked, then do Task.objects.filter('Online'=True/False).

I tried to add the following:

import django_filters
from app.models import Task
from django.db import models

class TaskFilter(django_filters.FilterSet):
    online = django_filters.BooleanFilter(name='online', lookup_expr='isnull')

    class Meta:
        model = Task
        fields = ['online']
        filter_overrides = {
            models.BooleanField: { 
                'filter_class': django_filters.BooleanFilter,
                'extra': lambda f: {
                    'widget': forms.CheckboxInput,
                },
            },
        }

I tried the following widgets: Select, RadioSelect, CheckboxInput, but it seems I get the same output for all of them. I get a dropdown list e.g.

Online: [ Dropdown to select a value from Yes, No, Unknown ]


Solution

  • You can use choices for that kind of stuff:

    TYPE_CHOICES = (
        (0, 'Online'),
        (1, 'Physical'),
    )
    class Task(models.Model):
        type = models.CharField(
            choices=TYPE_CHOICES, default=0, max_length=100
        )
        objects = TaskQuerySet().as_manager()
    

    Then you can filter it as usual:

    Task.objects.filter(type=0).filter(...)
    

    And to make it more easier you may add a custom queryset class:

    class TaskQuerySet(models.QuerySet):
        def get_online(self):
            return self.filter(type=0)
    
        def get_physical(self):
            return self.filter(type=1)
    

    That will allow you to do things like:

    Task.objects.get_online.filter(...)
    Task.objects.get_physical.filter(...)
    

    In the filters.py add:

    type = django_filters.MultipleChoiceFilter(field_name='type', choices=CHOICES, widget=forms.CheckboxSelectMultiple)