最后,在深入研究了django滤袋和
django_filters
这就是解决方案:
而不是定义一个新的习惯
FilterSet
FilterBackend
并覆盖
filter_queryset
方法。
过滤器.py
from django.db.models import Q
from django_filters import rest_framework as filters
from dry_rest_permissions.generics import DRYPermissionFiltersBase
from rest_framework import filters as generic_filters
# Project Local
from . import models, constants
from shootsta.users import models as users_models
class BookingFilterBackend(DRYPermissionFiltersBase):
def filter_list_queryset(self, request, queryset, view):
if request.user.is_role_admin:
return queryset
if request.user.is_role_client:
return queryset.filter(Q(client=request.user.client))
if request.user.is_role_camop:
return queryset.filter(Q(camera_operator=request.user))
return queryset.filter(Q(created_by=request.user))
# This is my new filter backend (I know the filtration logic looks very basic, I've come from a java background so spare me the rant.)
class MyNewFilterBackend(generic_filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
predicate = request.data
if all(k in predicate for k 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'])
if 'recipients' in predicate:
queryset = queryset.filter(users__uuid__in=predicate['recipients'])
return queryset
这是我的api.py,我刚刚将这个新的过滤器后端添加到列表中。
api.py公司
class MyViewSet(
MultipleSerializerMixin,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet
):
...
filter_backends = [filters.BookingFilterBackend, filters. MyNewFilterBackend, DjangoFilterBackend, ]
...
# This is the api which receives filteration form data from frontend.
@list_route(methods=['POST'], url_path='export-bookings')
def export_bookings(self, request, *args, **kwargs):
queryset = self.get_queryset()
# filter results!
filtered_queryset = self.filter_queryset(queryset)
tasks.generate_export_data_and_notify_accounts(filtered_queryset)
return response.NoContent()
我仍然在想我是否可以用FilterSets实现这一点。