DRF SearchFilter使用DateTimeField的gte查询报错问题
Django DRF中使用SearchFilter过滤DateTime字段日期范围报错的解决方法
在Django Shell中,对Order模型的timestamp(DateTime类型)字段使用timestamp__date__gte过滤可以正常返回结果:
$ python manage.py shell >>> from inventory.models import Order >>> Order.objects.filter(timestamp__date__gte=('2022-06-06')) <QuerySet [<Order: ID: 22>, <Order_id: 27>, ....]>
但在DRF的ListAPIView中使用SearchFilter时,会抛出以下错误:
django.core.exceptions.FieldError: Unsupported lookup 'gte' for DateField or join on the field not permitted, perhaps you meant gte or gt or lte?
相关代码:
models.py
class Order(models.Model): timestamp = models.DateTimeField(auto_now_add=True)
views.py(报错版本)
from rest_framework.generics import ListAPIView from rest_framework import filters class Invoices(ListAPIView): serializer_class = InvoicesSerializer permission_classes = [IsAuthenticated, CustomModelPermissions] queryset = serializer_class.Meta.model.objects.all() filter_backends = [filters.SearchFilter] search_fields = ['timestamp__date__gte']
错误原因
SearchFilter的作用是对指定字段执行模糊搜索,它的search_fields参数只能填写字段名,不能附加__gte这类查询条件后缀。你把timestamp__date__gte写进search_fields后,DRF会将其解析为要对某个字段执行gte查询,但timestamp__date是Date类型,Django无法识别这种错误的字段+查询条件组合,因此抛出异常。
解决方案
要实现日期范围过滤,应该使用DRF配套的DjangoFilterBackend,而非SearchFilter,步骤如下:
- 安装django-filter(未安装时执行):
pip install django-filter
- 在settings.py中添加应用:
INSTALLED_APPS = [ # ...其他已安装应用 'django_filters', ]
- 修改views.py配置过滤规则:
方式一:简单配置(直接支持gte/lte查询)
from rest_framework.generics import ListAPIView from django_filters.rest_framework import DjangoFilterBackend class Invoices(ListAPIView): serializer_class = InvoicesSerializer permission_classes = [IsAuthenticated, CustomModelPermissions] queryset = serializer_class.Meta.model.objects.all() filter_backends = [DjangoFilterBackend] # 前端可通过?timestamp__date__gte=2022-06-06传入过滤参数 filterset_fields = {'timestamp__date': ['gte', 'lte']}
方式二:自定义FilterSet(更简洁的参数命名)
如果希望前端参数更直观(比如用start_date代替timestamp__date__gte),可以自定义FilterSet:
# 可单独创建filters.py文件,或写在views.py中 import django_filters from inventory.models import Order class OrderFilter(django_filters.FilterSet): start_date = django_filters.DateFilter(field_name='timestamp__date', lookup_expr='gte') end_date = django_filters.DateFilter(field_name='timestamp__date', lookup_expr='lte') class Meta: model = Order fields = ['start_date', 'end_date'] # 修改View配置 class Invoices(ListAPIView): serializer_class = InvoicesSerializer permission_classes = [IsAuthenticated, CustomModelPermissions] queryset = serializer_class.Meta.model.objects.all() filter_backends = [DjangoFilterBackend] filterset_class = OrderFilter
此时前端可通过?start_date=2022-06-06过滤日期大于等于指定值的订单。
内容的提问来源于stack exchange,提问作者Fathy
相关产品推荐
相关产品推荐

