Does @action decorator only work for ModelViewSet?

Viewed 530

Does the @action decorator only work for viewsets.ModelViewSets?

Can I use the @action decorator for say a generics.RetrieveAPI?

If so, how? E.g. the following doesn't work:

class ItemDetailView(generics.RetrieveAPI):
    queryset = Item.objects.all()
    serializer_class = ItemDetailSerializer

    @action(detail=True, methods=["get"])
    def custom(self, request, pk=None):
        # Do whatever custom action
        return Response(status=status.HTTP_200_OK)
4 Answers

ModelViewSet has default action such as list, put, etc, @action decorators are used for defining user-defined actions on the same modalviewset and can be mapped to urls.

Generics views are defined based on roles, for example, each view class (listApiView or RetrieveApiView, etc) has its own work to do (action), so I think action decorators are not to be used here.

what you can do is use the get_queryset method and define your own customized query, also you can read query params from url in your get method and change your query based on params value. So you can get your desired result.

Hope this helps and btw I'm not 100% sure about action decorators in generic views.

Both Faisal and Ranu make a valid point - you can't and shouldn't define custom actions for generics.X views.
I would just add a reference from the actual implementation:

Custom actions work for anything extending viewsets.ViewSetMixin: viewsets.ViewSet, viewsets.GenericViewSet, viewsets.ModelViewSet etc.
Here is the as_view method from ViewSetMixin that handles custom actions.

class ViewSetMixin:
    """
    This is the magic.
    
    Overrides `.as_view()` so that it takes an `actions` keyword that performs
    the binding of HTTP methods to actions on the Resource.
    
    For example, to create a concrete view binding the 'GET' and 'POST' methods
    to the 'list' and 'create' actions...
    view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
    """

On the other hand, generics do not have such feature (here's the code).

Can I use the @action decorator for say a generics.RetrieveAPI?

The short answer would be No, By default, it is not allowed to use actions.

The reason is that RetrieveAPIView extends REST framework's GenericAPIView, RetrieveModelMixin classes, adding commonly required behaviour for standard list and detail views. And provides the default set of get_object, get_queryset methods and other generic view base behavior, but does not include any actions by default. But you can override the class and either mixin the required mixin classes, or can define the action implementations explicitly. Explore Docs For More Details

Does the @action decorator only work for viewsets.ModelViewSets?

Anser would be No, custom actions work for anything extending from ViewSetMixin including ModelViewSets.

@action mark a ViewSetMixin method as a routable action. In ViewSetMixin Overrides .as_view() so that it takes an actions keyword that performs the binding of HTTP methods to actions on the Resource. So this decorator just works in every class that in inherit from ViewSetMixin. For example:

  • ViewSet
  • GenericViewSet
  • ReadOnlyModelViewSet
  • ModelViewSet
  • ...
Related