Reputation: 3084
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 ]
Upvotes: 2
Views: 7733
Reputation: 111
Filters accept a widget argument, so you if you're manually instantiating filters, you can use:
class TaskFilter(django_filters.FilterSet):
online = django_filters.filters.BooleanFilter(widget=forms.CheckboxInput)
class Meta:
model = Task
fields = ['online']
However, if you're using the meta class to declare fields, then you can override the behavior with filter_overrides
class TaskFilter(django_filters.FilterSet):
filter_overrides = {
models.BooleanField: {
'filter_class': filters.BooleanFilter,
'extra': lambda f: {
widget: forms.CheckboxInput
},
}
}
class Meta:
model = MyModel
fields = ['online']
After a lot of testing though, I came to a conclusion that is usually helpful for default=False
model fields.
Upvotes: 3
Reputation: 1238
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)
Upvotes: 3