I have the following code:
class MyViewSet(ModelViewSet):
...
filter_backends = (...)
def dispatch(self, request, *args, **kwargs):
response = super(MyViewSet, self).dispatch(
request,
*args,
**kwargs
)
... # do something with the response
return response
Inside the dispatch method, I can retrieve the filtered data with response.data
, so I assume the custom filter backend is working properly. However, I also want to do something with the queryset as well (eg call count()
), after the filter has been applied to it. The problem is that self.queryset
and self.get_queryset()
return the whole, non-filtered queryset.
So how do get the version of queryset to which the filter has been applied in the dispatch method, if it's possible at all?
You could use the filter_queryset
method. It will filter it with whichever filter backend is in use. See its definition in GenericAPIView
class.
def filter_queryset(self, queryset):
"""
Given a queryset, filter it with whichever filter backend is in use.
You are unlikely to want to override this method, although you may need
to call it either from a list view, or from a custom `get_object`
method if you want to apply the configured filtering backend to the
default queryset.
"""
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
So you can filter the queryset like,
filtered_queryset = self.filter_queryset(self.get_queryset())
# Then do something with the filtered queryset
Note that self.filter_queryset(self.get_queryset())
will filter the queryset again even if the queryset was already filtered during the following super
call
super(MyViewSet, self).filter_queryset(
self.queryset()
).
Following is one way to overcome the duplicate filter call. You could override the filter_queryset
method and attach the filtered queryset to the instance.( please note that this solution is not tested )
ie, something like this.
class MyViewSet(ModelViewSet):
...
filter_backends = (...)
def dispatch(self, request, *args, **kwargs):
response = super(MyViewSet, self).dispatch(
request,
*args,
**kwargs
)
... # do something with the response
# After this super call `_filtered_query_set` attribute will be set.
# so use `self._filtered_query_set` wherever needed
return response
def filter_queryset(self, queryset):
filtered_query_set = super(MyViewSet, self).filter_queryset(
self.queryset()
)
self._filtered_query_set = filtered_query_set
return filtered_query_set
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.