I have many endpoints which use ModelViewSet
to manage CRUD operations for my models.
What I am trying to do, is to add bulk create, update, and delete at these same endpoints. In other words, I want to add POST
, PUT
, PATCH
and DELETE
to the collection endpoint (e.g.: /api/v1/my-model
). There is a django-rest-framework-bulk
package available, but it seems to be abandoned (hasn't been updated in 4 years) and I'm not comfortable using a package in production that is no longer active.
Additionally, There are several similar questions here that have solutions, as well as blog posts I've found. However, they all seem to use the base ViewSet
, or APIView
, which would require re-writing all of my existing ModelViewSet
code.
Finally, there is the option of using the @action
decorator, however this would require me to have a separate list endpoint (e.g.- /api/v1/my-model/bulk
) which I'd like to avoid.
Are there any other ways to accomplish this while keeping my existing ModelViewSet
views? I've been looking at GenericViewSet
and mixins, and am wondering if creating my own mixin might be the way to go. However, looking at the mixin code, it doesn't appear that you can specify an HTTP Request method to be attached to a given mixin.
Finally, I have tried creating a separate ViewSet
that accepts PUT and adding it to my URLs, but this doesn't work (I get a 405 Method not allowed when I try to PUT to /api/v1/my-model
). The code I tried looks like this:
# views.py
class MyModelViewSet(viewsets.ModelViewSet):
serializer_class = MyModelSerializer
permission_classes = (IsAuthenticated,)
queryset = MyModel.objects.all()
paginator = None
class ListMyModelView(viewsets.ViewSet):
permission_classes = (IsAuthenticated,)
def put(self, request):
# Code for updating list of models will go here.
return Response({'test': 'list put!'})
# urls.py
router = DefaultRouter(trailing_slash=False)
router.register(r'my-model', MyModelViewSet)
router.register(r'my-model', ListMyModelView, base_name='list-my-model')
urlpatterns = [
path('api/v1/', include(router.urls)),
# more paths for auth, admin, etc..
]
Thoughts?