Home > OS >  How to assign multiple api views to single endpoint in django rest framework?
How to assign multiple api views to single endpoint in django rest framework?

Time:11-24

I have a model named Article and a few api views for it. They are divided for diffrent purposes (for example ArticleUpdateAPI class for UPDATE http method, ArticleDeleteAPI for DELETE method etc). In urls.py they are separated to diffrent endpoints (aritcle/pk/update, /article/pk/delete etc).

As I know, it's not good practice to build endpoint like this, so I want to bind them to single url and use diffrent classes for handling diffrent http methods. Is it possible and how? Examples are below

ArticleAPI.py

class ArticlePostAPI(generics.CreateAPIView):
    serializer_class = ArticleSerializer
    permission_classes = [
        permissions.IsAuthenticatedOrReadOnly
    ]

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response({
            "comment": CommentSerializer.data
        }, status=201)


class ArticleRetrieveAPI(generics.RetrieveAPIView):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    permission_classes = [
        permissions.AllowAny
    ]


class ArticleListAPI(generics.ListAPIView):
    serializer_class = ArticleSerializer
    queryset = Article.objects.order_by('number', 'headline')
    permission_classes = [
        permissions.AllowAny
    ]


class ArticleUpdateAPI(generics.UpdateAPIView):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    permission_classes = [
        permissions.IsAuthenticated
    ]

    lookup_field = 'pk'

    def update(self, request, *args, **kwargs):
        instance = self.get_object()

        if request.user != instance.author:
            return Response({
               "errors": "Logged in user and author must be same"
            }, status=403)

        serializer = self.get_serializer(instance, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        return Response(serializer.data)

urls.py

urlpatterns = [
    ...

    # Article API

    path('article/post/', ArticlePostAPI.as_view(), name='article_creation'),
    path('article/<int:pk>/', ArticleRetrieveAPI.as_view(), name='article_retrieve'),
    path('article/', ArticleListAPI.as_view(), name='article_list'),
    path('article/<int:pk>/update/', ArticleUpdateAPI.as_view(), name='article_update'),
]

CodePudding user response:

Use ModelViewSet for simplifying it.

Using this you can perform all http method actions with a single url and single view.

from rest_framework import viewsets


class ArticleView(viewsets.ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    permission_classes = [permissions.AllowAny]

urls.py

router = DefaultRouter()
router.register(r'articles', views.ArticleView, basename='articles')

here

GET - /articles/ - gives list of all articles
GET - /articles/id/ - gives one object
POST - /articles/ - creates an article
PUT - /articles/id/ - updates an article
PATCH - /articles/id/ - partially updates an article
DELETE - /articles/id/ - deletes an article
  • Related