[PYTHON] Change the suffix of django-filter / DateFromToRangeFilter

to write

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.

Preparation

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"}]

policy

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

  1. Create a Custom Widget
  2. Create CustomDateRangeField
  3. Create CustomDateFromToRangeFilter I decided to implement it like this.

Implementation

1. Create a Custom Widget

Make sure the suffix is _from, _to

widgets.py


from django_filters.widgets import DateRangeWidget


class CustomDateRangeWidget(DateRangeWidget):
    suffixes = ['from', 'to']

2. Create CustomDateRangeField

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

3. Create CustomDateFromToRangeFilter

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.

Finally

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

Change the suffix of django-filter / DateFromToRangeFilter
Change the theme of Jupyter
Change the style of matplotlib
Change the background of Ubuntu (GNOME)
Change the Python version of Homebrew
Change the length of Python csv strings
Script to change the description of fasta
Change the order of PostgreSQL on Heroku
Change the destination batfish server of pybatfish
Change the font size of the legend in df.plot
Change the color of Fabric errors and warnings
Change the decimal point of logging from, to.
Change the resolution of Ubuntu running on VirtualBox
[Touch Designer] Change the appearance color of Button COMP
The meaning of self
the zen of Python
The story of sys.path.append ()
[Django] Change the Default IP address of the runserver command
Revenge of the Types: Revenge of types
[Python] Let's change the URL of the Django administrator site
An introduction to object orientation-let's change the internal state of an object
Change the log retention period of CloudWatch Logs in Lambda
Change the volume of Pepper according to the surrounding environment (sound)
Align the version of chromedriver_binary
Scraping the result of "Schedule-kun"
10. Counting the number of lines
Towards the retirement of Python2
Get the number of digits
Explain the code of Tensorflow_in_ROS
Reuse the results of clustering
GoPiGo3 of the old man
Calculate the number of changes
The popularity of programming languages
Visualize the orbit of Hayabusa2
About the components of Luigi
Connected components of the graph
Filter the output of tracemalloc
About the features of Python
Simulation of the contents of the wallet
The Power of Pandas: Python
How to change the log level of Azure SDK for Python
How to change the color of just the button pressed in Tkinter
Change the Y-axis scale of Matplotlib to exponential notation (10 Nth power notation)
Find out the mystery change of Pokédex description by Levenshtein distance
Feel free to change the label of the legend in Seaborn in python
[Go] Create a CLI command to change the extension of the image
I summarized how to change the boot parameters of GRUB and GRUB2
What happens when I change the hyperparameters of SVM (RBF kernel)?