Reputation: 44501
Currently my view is as follows:
from rest_framework.permissions import AllowAny
from dynamic_rest.viewsets import DynamicModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
from .models import Purchase
from .serializers import PurchaseSerializer
class PurchasesViewSet(DynamicModelViewSet):
queryset = Purchase.objects.all()
serializer_class = PurchaseSerializer
permission_classes = (AllowAny,)
filter_backends = (DjangoFilterBackend,)
filter_fields = ('name', 'color')
Which allows me to filter by exact name
and color
.
My data has a date
field (DateField
type). I would like to create a custom filter by "quarter", so that this kind of request:
/purchases/?quarter=2018Q1
provides a list of objects with date
field in the specified quarter. Note that quarter
is not a model field.
What would the approach of creating such a custom filter?
Upvotes: 2
Views: 561
Reputation: 88689
First, you have to create custom filter along with filter class
import django_filters
from rest_framework.exceptions import ValidationError
class QuarterFilter(django_filters.Filter): # Custom Filter
def get_quarter_range(self, quarter):
if quarter == 1:
return [1, 3]
elif quarter == 2:
return [4, 6]
elif quarter == 3:
return [7, 9]
elif quarter == 4:
return [10, 12]
else:
raise ValidationError("quarter value must be range from 1-4")
def filter(self, qs, value):
"""
create your custom filtering logi here
"""
# here the "value" will be the value parsed from URL params, ie "2018Q1"
try:
year, quarter = value.split("Q") # spliting the input to get year and quarter value
qs = qs.filter(date__year=year)
qs = qs.filter(date__month__range=self.get_quarter_range(quarter))
return qs
except:
return qs
class PurchaseFilter(django_filters.FilterSet): # Custom Filter Class
quarter = QuarterFilter()
class Meta:
model = Purchase
fields = ['name', 'color', 'quarter']
Then, mention it in your view class with filterset_class
attribute. Then your view be like,
class PurchasesViewSet(DynamicModelViewSet):
queryset = Purchase.objects.all()
serializer_class = PurchaseSerializer
permission_classes = (AllowAny,)
filter_backends = (DjangoFilterBackend,)
# filter_fields = ('name', 'color') ---- Remove this line of code
filterset_class = PurchaseFilter
NOTE
I'm not sure about this line,
qs = qs.filter(date__month__range=self.get_quarter_range(quarter))
But, this is how you need to do filtering in this particular case.
Hope this helps!!
Upvotes: 2
Reputation: 1450
you can create custom filter in filter_class
from rest_framework import filters
class CustomFilter(django_filters.rest_framework.FilterSet):
class Meta:
model = Purchase
fields = ['name', 'color', 'quarter']
quarter = QuarterFilter(name="quarter")
class QuarterFilter(django_filters.Filter):
def filter(self, qs, value):
# create custom in this with value
return qs.filter(name=value)
class PurchasesViewSet(DynamicModelViewSet):
queryset = Purchase.objects.all()
serializer_class = PurchaseSerializer
permission_classes = (AllowAny,)
filter_backends = (DjangoFilterBackend,)
filter_class = CustomFilter
Upvotes: 2