Django Filters:建议改进动态过滤逻辑
Django Filters: Suggest improvements to dynamic filtering logic
我正在根据用户在前端 select 提供的多种搜索条件对我的数据集进行过滤。以下是一些注意事项:
- 所有过滤条件都不是强制性的。用户可以 select/enter 值或将其留空。后端必须找出一种检查 NULL 的方法。
- 下拉列表是多个 select 因此过滤器表单数据可以有多个 ID 列表。 (很多 IN 查询)
- 还有 DATE (from/to) 相关字段,可以留空。因此代码必须处理以下场景:日期范围过滤 |日期 > DDMMYYYY |日期 < DDMMYYYY.
表单如下所示:
这是我目前的做法:
class BookingExportFilterBackend(generic_filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
predicate = request.data
if all(dt in predicate for dt in ('from_date', 'to_date')):
queryset = queryset.filter(date__range=(predicate['from_date'], predicate['to_date']))
if 'from_date' in predicate and 'to_date' not in predicate:
queryset = queryset.filter(date__gte=predicate['from_date'])
if 'to_date' in predicate and 'from_date' not in predicate:
queryset = queryset.filter(date__lte=predicate['to_date'])
if 'state' in predicate:
queryset = queryset.filter(state__in=predicate['state'])
if 'clients' in predicate:
queryset = queryset.filter(client__in=predicate['clients'])
if 'camera_operators' in predicate:
queryset = queryset.filter(camera_operator__uuid__in=predicate['camera_operators'])
return queryset
感觉还可以改进,尤其是日期部分。我也在使用 Q
库,但我对 Django 还很陌生。 (PS:我来自 Java/Spring/Hibernate 背景)。
请帮助改进代码。
您应该尝试使用 django-filters 库进行过滤。它使用起来非常简单,并提供了一系列过滤选项。
对于你的情况,你可以从这样的事情开始:
注意:请不要使用日期作为 field/variable 名称,我在下面的示例中已替换为 booking_date。
class BookingFilter(django_filters.FilterSet):
from_date = django_filters.NumberFilter(field_name='booking_date', lookup_expr='gt')
to_date = django_filters.NumberFilter(field_name='booking_date', lookup_expr='lt')
status = django_filters.CharFilter(name="status", lookup_type="contains"
class Meta:
model = Booking # replace with your appropriate Model
我正在根据用户在前端 select 提供的多种搜索条件对我的数据集进行过滤。以下是一些注意事项:
- 所有过滤条件都不是强制性的。用户可以 select/enter 值或将其留空。后端必须找出一种检查 NULL 的方法。
- 下拉列表是多个 select 因此过滤器表单数据可以有多个 ID 列表。 (很多 IN 查询)
- 还有 DATE (from/to) 相关字段,可以留空。因此代码必须处理以下场景:日期范围过滤 |日期 > DDMMYYYY |日期 < DDMMYYYY.
表单如下所示:
这是我目前的做法:
class BookingExportFilterBackend(generic_filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
predicate = request.data
if all(dt in predicate for dt in ('from_date', 'to_date')):
queryset = queryset.filter(date__range=(predicate['from_date'], predicate['to_date']))
if 'from_date' in predicate and 'to_date' not in predicate:
queryset = queryset.filter(date__gte=predicate['from_date'])
if 'to_date' in predicate and 'from_date' not in predicate:
queryset = queryset.filter(date__lte=predicate['to_date'])
if 'state' in predicate:
queryset = queryset.filter(state__in=predicate['state'])
if 'clients' in predicate:
queryset = queryset.filter(client__in=predicate['clients'])
if 'camera_operators' in predicate:
queryset = queryset.filter(camera_operator__uuid__in=predicate['camera_operators'])
return queryset
感觉还可以改进,尤其是日期部分。我也在使用 Q
库,但我对 Django 还很陌生。 (PS:我来自 Java/Spring/Hibernate 背景)。
请帮助改进代码。
您应该尝试使用 django-filters 库进行过滤。它使用起来非常简单,并提供了一系列过滤选项。
对于你的情况,你可以从这样的事情开始: 注意:请不要使用日期作为 field/variable 名称,我在下面的示例中已替换为 booking_date。
class BookingFilter(django_filters.FilterSet):
from_date = django_filters.NumberFilter(field_name='booking_date', lookup_expr='gt')
to_date = django_filters.NumberFilter(field_name='booking_date', lookup_expr='lt')
status = django_filters.CharFilter(name="status", lookup_type="contains"
class Meta:
model = Booking # replace with your appropriate Model