I am currently trying to use BaseInFilter. Users can input the ids separated by commas like the one shown in the picture. I want to make a validator(or regulate user's input) so that the user can only input integers here.
If the user enters characters, the Django backend will throw out this error.
I have also tried this:
class BaseIntegerFilter(filters.BaseInFilter, filters.NumberFilter):
pass
class HardwareFilter(filters.FilterSet):
queryset = Hardware
serializer_class = HardwareSerializer
id = filters.BaseIntegerFilter(field_name="id", label="Comma separated list of hardware IDs", help_text="Comma separated list of hardware IDs")
But this solution doesn't allow me to input commas in the textbox anymore.
Could anyone help? Any help will be really appreatiated!
Here is some guidance with regards to usage.
filterset_class
with BaseInFilter
queryset
and serializer_class
are fields of view classes, not filter classes.views.py:
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import viewsets
from my_app.filters import MyFilter
from my_app.models import MyModel
from my_app.serializers import MySerializer
class MyViewSet(viewsets.ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MySerializer
filter_backends = [DjangoFilterBackend]
filterset_class = MyFilter
lookup_field = 'id'
filters.py:
from django_filters.rest_framework import BaseInFilter, FilterSet, NumberFilter
from my_app.models import MyModel
class _NumberInFilter(BaseInFilter, NumberFilter):
pass
class MyFilter(FilterSet):
id__in = _NumberInFilter(field_name='id', lookup_expr='in')
class Meta:
model = MyModel
fields = '__all__'
HTTP request (numbers):
$ curl http://127.0.0.1:8000/my_app/my_view_set/?id__in=2,5,6
[{"id":5,"name":"Some name 5"},{"id":2,"name":"Some name 2"},{"id":6,"name":"Some name 6"}]
id__in
and not just id
.curl
was used here. For easier access, you can also enter it in a browser, Postman, etc.HTTP request (numbers and letters):
$ curl http://127.0.0.1:8000/my_app/my_view_set/?id__in=2,5FD,6
{"id__in":["Enter a number."]}
filterset_fields
views.py:
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import viewsets
from my_app.models import MyModel
from my_app.serializers import MySerializer
class MyViewSet(viewsets.ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MySerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = {'id': ['in']}
lookup_field = 'id'
HTTP request:
filterset_class
The HTTP requests performed above are manual, without using the UI provided by djangorestframework
. Upon trying it with the UI, I experienced the same problem as you stated:
But this solution doesn't allow me to input commas in the textbox anymore.
This is not related to the filtering mechanism provided by django_filters
(which happens in the backend) as this is a pure frontend issue specifically with the form validation.
A manual workaround I did was inspect the textbox (right-click + inspect) then update the HTML line from number
to text
. So from:
<input type="number" name="id__in" step="any" id="id_id__in">
To:
<input type="text" name="id__in" step="any" id="id_id__in">
HTTP request (numbers and letters):
You may want to intercept the actual rendering of the HTML by the djangorestframework
or django_filters
to do this cleanly.