I implemented Django Rest Framework and so far so good.
Pagination function ok and Ordering works as well as expected
But somehow filtering does not work on views.
1). djago-filters
Since it seems to be simple and flexible, I attempted use it.
By execution shell, it function as expected,
But when I call it from views.py, it does not work and simply return all results
Is there anything wrong or bug?
Ubuntu 22.04
Python 3.10.12
Django 4.2.6
django-filter 23.3
djangorestframework 3.14.0
*filters.py
import django_filters
from django_filters import rest_framework as dj_filters
from .models import Customer
class CustomerFilter(dj_filters.FilterSet):
# exact only
id = django_filters.NumberFilter()
cd = django_filters.CharFilter()
type = django_filters.CharFilter(lookup_expr="exact")
branch_cd = django_filters.CharFilter()
institution_cd = django_filters.CharFilter()
# exact & icontains
name = django_filters.CharFilter(lookup_expr="exact")
name__icontains = django_filters.CharFilter(field_name="name", lookup_expr="icontains")
postal_cd = django_filters.CharFilter(lookup_expr="exact")
postal_cd__icontains = django_filters.CharFilter(field_name="postal_cd", lookup_expr="icontains")
city = django_filters.CharFilter(lookup_expr="exact")
city__icontains = django_filters.CharFilter(field_name="city", lookup_expr="icontains")
phone = django_filters.CharFilter(lookup_expr="exact")
phone__icontains = django_filters.CharFilter(field_name="phone", lookup_expr="icontains")
# icontains only
address1__icontains = django_filters.CharFilter(field_name="address1", lookup_expr="icontains")
address2__icontains = django_filters.CharFilter(field_name="address2", lookup_expr="icontains")
url__icontains = django_filters.CharFilter(field_name="url", lookup_expr="icontains")
# range
establish_date = django_filters.DateFromToRangeFilter()
register_at = django_filters.DateTimeFromToRangeFilter()
update_at = django_filters.DateTimeFromToRangeFilter()
delete_at = django_filters.DateTimeFromToRangeFilter()
number_of_employee = django_filters.RangeFilter()
class Meta:
model = Customer
fields = [
'id', 'cd', 'branch_cd', 'institution_cd', 'register_by', 'update_by', 'delete_by',
'name', 'kana', 'type', 'postal_cd', 'ken', 'city', 'phone', 'fax', 'establish_by',
'address1', 'address2', 'url',
'establish_date', 'register_at', 'update_at', 'delete_at', 'number_of_employee',
]
I called above Customer Filter from shell and it returned filtered result
But when I called from views.py, it just return all UN-filtered data
**views.py
from rest_framework import status, views, generics, filters
from rest_framework.response import Response
from .serializers import CustomerSerializer, DepartmentSerializer
from .models import Department, Customer
from .pagination import LimitPagination
from django_filters.rest_framework import DjangoFilterBackend
from .filters import CustomerFilter
class CustomerListView(generics.ListAPIView):
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
filterset_class = CustomerFilter
ordering_fields="__all__"
filtering_fields="__all__"
**setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_filters',
'rest_framework',
'customer',
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'rest_framework.filters.OrderingFilter',
'django_filters.rest_framework.DjangoFilterBackend',
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
}
Alternatively I attempted to use only filter function in views.py
it is very strange
**another attempt of views.py
from .pagination import LimitPagination
from django_filters.rest_framework import DjangoFilterBackend
from django.db.models import Q
from django.utils.dateparse import parse_date, parse_datetime
class CustomerListView(generics.ListAPIView):
serializer_class = CustomerSerializer
filter_backends = [filters.OrderingFilter]
ordering_fields="__all__"
filterset_fields="__all__"
def get_queryset(self):
logger.debug("get_queryset called")
queryset = Customer.objects.all()
#queryset = Customer.objects.filter(cd="00000030")
print("Before filtering:", queryset.query)
query_params = self.request.query_params
# exactとicontainsを一つのループで処理
filter_fields = [
'id', 'cd', 'type', 'branch_cd', 'institution_cd',
'register_by', 'update_by', 'delete_by', 'name', 'kana',
'postal_cd', 'ken', 'city', 'phone', 'fax', 'establish_by',
'address1', 'address2', 'url' # icontains専用のフィールドも含める
]
for field in filter_fields:
# exact
exact_value = query_params.get(field)
if exact_value is not None:
kwargs = {f"{field}": exact_value}
queryset = queryset.filter(**kwargs)
# icontainsフィルタ
icontains_value = query_params.get(f"{field}__icontains")
if icontains_value is not None:
kwargs = {f"{field}__icontains": icontains_value}
queryset = queryset.filter(**kwargs)
return queryset
Execution
python manage.py shell
from django.test.client import RequestFactory
from customer.views import CustomerListView
factory = RequestFactory()
request = factory.get('/your-url/', {'cd': '00000100'})
view = CustomerListView()
view.setup(request)
view.get_queryset() #No print output nor logger output!!!
queryset = view.get_queryset()
queryset.query #SQL does not contain where so no filtering SQL generated
Could you please help what is going on my view?
GPT is not smart enough to resolve this for me (**)