Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7k
Description
We have a couple custom@action-annotatedcount functions, withdetail=False. They do show up in the browsable API, however, noOPTIONS button is rendered for them.
I noticed this while trying to figure out how to get it to show the "Filters" button for those actions, because basically I'm trying to get some aggregated information (count, using some grouping) on a filtered query.
This is what I found out:
Our base code, where filtering works fine via URL, but neither "OPTIONS", nor "Filters" appears as a button:
# Settings:fromconfigurationsimportConfigurationclassConfig(Configuration): ...REST_FRAMEWORK= { ..."DEFAULT_FILTER_BACKENDS": ["rest_framework.filters.SearchFilter","rest_framework.filters.OrderingFilter","django_filters.rest_framework.DjangoFilterBackend", ], } ...# View set:classSomeViewSet(ModelViewSet): ...@action(detail=False,methods=[HTTPMethod.GET],pagination_class=None, )defcount(self,request):raw_data=self.filter_queryset(self.get_queryset() .values("status") .annotate(count=Count("status")) .order_by("status") )data= {"grouping": ["status"],"items": {item["status"]:item["count"]foriteminraw_data}, }returnResponse(status=status.HTTP_200_OK,data=data)
Changing the annotation as follows will cause an error when querying the API:
# import settings in the file...fromdjango.confimportsettings...@action(detail=False,methods=[HTTPMethod.GET],filter_backends=settings.REST_FRAMEWORK.get("DEFAULT_FILTER_BACKENDS")),pagination_class=None,)
The error says:
File "/.../backend-django/.venv/lib/python3.13/site-packages/rest_framework/generics.py", line 154, in filter_queryset queryset = backend().filter_queryset(self.request, queryset, self) ~~~~~~~^^ TypeError: 'str' object is not callableNow, changing theDEFAULT_FILTER_BACKENDS config to point to actual classes, like the following, will result in an "OPTIONS" button being shown, and the request now runs without error again. However, this change causes other problems such as pagination on other (e.g. list) endpoints to be entirely skipped:
fromconfigurationsimportConfigurationfromdjango.utils.module_loadingimportimport_stringclassConfig(Configuration): ...REST_FRAMEWORK= { ..."DEFAULT_FILTER_BACKENDS": [import_string(item)foritemin ["rest_framework.filters.SearchFilter","rest_framework.filters.OrderingFilter","django_filters.rest_framework.DjangoFilterBackend", ] ], } ...
This is of course undesirable, so let's not do that. Another attempt, with the above change reverted, changing the@action annotation instead. Unfortunately, no "OPTIONS" or "Filters" button show up with this:
@action(detail=False,methods=[HTTPMethod.GET],filter_backends=tuple(import_string(item)foriteminsettings.REST_FRAMEWORK.get("DEFAULT_FILTER_BACKENDS")),)
I'm not sure what's going on, but it seems to me that something is wrong with the logic behind whether or not to show the "OPTIONS" and "Filters" buttons.