If you use DateFromToRangeFilter ()
provided by django-filter, the suffix of the specified field will be _after
and _before
by default. It picks up the attached items and narrows them down to that range.
However, this time I wanted to pick up _from
and _to
and narrow down the range.
It took a while, so I will write it as a record.
I also mentioned it on GitHub.
Create a BlogModel
with a created_at
column and create an endpoint to get that list.
models.py
from django.db import models
class Blog(models.Model):
title = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
serializers.py
from rest_framework.serializers import ModelSerializer
from blogs.models import Blog
class BlogSerializer(ModelSerializer):
class Meta:
model = Blog
fields = '__all__'
filters.py
from django_filters import rest_framework as filters
from blogs.models import Blog
class BlogFilter(filters.FilterSet):
created_at = filters.DateFromToRangeFilter()
class Meta:
model = Blog
fields = ['created_at']
views.py
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from blogs.filters import BlogFilter
from blogs.models import Blog
from blogs.serializers import BlogSerializer
class BlogViewSet(ViewSet):
def list(self, request):
queryset = Blog.objects.all()
queryset = BlogFilter(data=request.GET, queryset=queryset, request=request).qs
serializer = BlogSerializer(queryset, many=True)
return Response(serializer.data)
urls.py
from rest_framework.routers import DefaultRouter
from blogs.views import BlogViewSet
router = DefaultRouter(trailing_slash=False)
router.register(
r'^blogs',
BlogViewSet,
basename='blogs'
)
urlpatterns = router.urls
Finally, create a record in the Blog table on February 24, 2020
.
>>> blog1 = Blog.objects.create(title='blog1')
<Blog: Blog object (1)>
>>> blog1.created_at
datetime.datetime(2020, 2, 24, 5, 54, 52, 859528, tzinfo=<UTC>)
You can now specify the range by passing the query parameters created_at_after
and created_at_before
to / blogs
.
>>> curl 'http://localhost:18000/blogs?created_at_after=2020-02-01&created_at_before=2020-02-02'
[]
>>> curl 'http://localhost:18000/blogs?created_at_after=2020-02-01&created_at_before=2020-02-28'
[{"id":1,"title":"blog1","created_at":"2020-02-24T05:54:52.859528Z"}]
What I want to do this time is to change the default suffix _after
, _before
.
I thought about finding the setting and overriding it if possible.
Let's take a look inside DateFromToRangeFilter
.
DateFromToRangeFilter(GitHub)
Then you can see that the suffix is set like this in DateRangeWidget (GitHub). It was.
class DateRangeWidget(RangeWidget):
suffixes = ['after', 'before']
It's used in DateRangeField (GitHub).
From the above
Make sure the suffix is _from
, _to
widgets.py
from django_filters.widgets import DateRangeWidget
class CustomDateRangeWidget(DateRangeWidget):
suffixes = ['from', 'to']
Create a Field to use for Filter using CustomWidget.
fields.py
from django_filters.fields import DateRangeField
from blogs.widgets import CustomDateRangeWidget
class CustomDateRangeField(DateRangeField):
widget = CustomDateRangeWidget
Create a Filter using the CustomDateRangeField
created in 2.
filters.py
from django_filters import rest_framework as filters
from blogs.fields import CustomDateRangeField
from blogs.models import Blog
class CustomDateRangeFilter(filters.DateFromToRangeFilter):
field_class = CustomDateRangeField
class BlogFilter(filters.FilterSet):
# created_at = filters.DateFromToRangeFilter()
created_at = CustomDateRangeFilter()
class Meta:
model = Blog
fields = ['created_at']
Of course, the default _after
and _before
cannot be used.
I will confirm it.
_after,_Try not to be able to use before
>>> curl 'http://localhost:18000/blogs?created_at_after=2020-02-01&created_at_before=2020-02-02'
[{"id":1,"title":"blog1","created_at":"2020-02-24T05:54:52.859528Z"}]
>>> curl 'http://localhost:18000/blogs?created_at_after=2020-02-01&created_at_before=2020-02-28'
[{"id":1,"title":"blog1","created_at":"2020-02-24T05:54:52.859528Z"}]
_from, _Try to work as expected
>>> curl 'http://localhost:18000/blogs?created_at_from=2020-02-01&created_at_to=2020-02-02'
[]
>>> curl 'http://localhost:18000/blogs?created_at_from=2020-02-01&created_at_to=2020-02-28'
[{"id":1,"title":"blog1","created_at":"2020-02-24T05:54:52.859528Z"}]
With the above, the suffix can be changed.
I haven't used django-filter
at all, but it's very convenient.
If anyone knows that "this can be solved more easily", I would be grateful if you could let me know.
__Thank you very much! __
Recommended Posts