Skip to content

Instantly share code, notes, and snippets.

@mariodev
Created September 24, 2013 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mariodev/6689472 to your computer and use it in GitHub Desktop.
Save mariodev/6689472 to your computer and use it in GitHub Desktop.
Custom filter field for django-filter. Control two fields in a flexible manner.
from django import forms
import django_filters
from django_filters.filters import Filter
CHOICES = (('AND', 'AND'), ('OR', 'OR'))
class NamePriceWidget(forms.MultiWidget):
def __init__(self, attrs=None):
widgets = (
forms.TextInput(attrs=attrs),
forms.Select(choices=CHOICES),
forms.TextInput(attrs=attrs)
)
super(NamePriceWidget, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
return [value.start, value.operator, value.value.stop]
return [None, None, None]
def format_output(self, rendered_widgets):
return '-'.join(rendered_widgets)
class NamePriceField(forms.MultiValueField):
widget = NamePriceWidget
def __init__(self, *args, **kwargs):
fields = (
forms.CharField(),
forms.ChoiceField(choices=CHOICES),
forms.DecimalField(),
)
super(NamePriceField, self).__init__(fields, *args, **kwargs)
def compress(self, data_list):
if data_list:
return data_list
return None
from django.db.models import Q
class NamePriceFilter(Filter):
field_class = NamePriceField
def filter(self, qs, value):
if value:
q_object = Q()
try:
operator = {'AND': Q.AND, 'OR': Q.OR}[value[1]]
except KeyError:
operator = Q.AND
if value[0]:
q_object = Q(name__startswith=value[0])
if value[2]:
q_object.add(Q(price__lte=value[2]), operator)
return qs.filter(q_object)
return qs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment