Implement HTTP methods in different APIView class in django
I have an API with 2 routes some_resource/ and some_resource/<id> and I would like to implement the normal CRUD actions (list, retrieve, create, update, delete). However, I don't want to use ViewSet because I want to have 1 class for each view. Thus I need to set up the route manually for clarity. :
class SomeResourceRetrieveView(APIView):
def get(self, request, pk, *args, **kwargs):
...
class SomeResourceListView(APIView):
def get(self, request, *args, **kwargs):
...
class SomeResourceCreateView(APIView):
def post(self, request, *args, **kwargs):
...
So in urls.py it looks like this
url_patterns = [
path("some_resource/", InvitationTeamAccessListAPI.as_view(), name="some-resource-list"),
path("some_resource/", InvitationTeamAccessCreateAPI.as_view(), name="some-resource-create"),
path("some_resource/<int:pk>", InvitationTeamAccessRetrieveAPI.as_view(), name="some-resource-retrieve"),
]
However when I use POST on some_resource/, I get a 405. I think django stops at the first matched route and doesn't find an implementation for post. Is there a way to plug all my views to the same pattern but keep them as separate classes?
You can make use of ViewSets
give this a try:
from rest_framework import viewsets
from rest_framework.response import Response
class InvitationTeamAccessViewSet(viewsets.ViewSet):
"""
Example empty viewset demonstrating the standard
actions that will be handled by a router class.
If you're using format suffixes, make sure to also include
the `format=None` keyword argument for each action.
"""
def list(self, request):
# this is your get() method
queryset = InvitationTeamAccess.objects.all()
# you should change your serializer name accordingly
serializer = InvitationTeamAccessSerializer(queryset, many=True)
return Response(serializer.data)
def create(self, request):
# this is your post method
# you have to write you post logic here
pass
def retrieve(self, request, pk=None):
# this is your get() details method
queryset = InvitationTeamAccess.get(pk=pk)
# you should change your serializer name accordingly
serializer = InvitationTeamAccessSerializer(queryset)
return Response(serializer.data)
def update(self, request, pk=None):
# write your post() method here
pass
def partial_update(self, request, pk=None):
pass
def destroy(self, request, pk=None):
pass
and in urls.py
from myapp.views import InvitationTeamAccess
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'some_resource/', InvitationTeamAccess, basename='InvitationTeamAccess')
urlpatterns = router.urls
then with single url path you can perform multiple actions
GET: some_resource/ will show the list of InvitationTeamAccess's
GET: some_resource/1/ will show the detail of a single InvitationTeamAccess
POST: some_resource/ will create new InvitationTeamAccess
also read about ModelVieset