[Fixed]-Django rest framework Router – how to add customized URL and view functions

12👍

Let me show how to use ViewSet and router:

According to defaultrouter, your viewset needs to declare the views in the class.

I give an example about user api and guide you as the following:

class UserViewSet(viewsets.ViewSet):
    """Userviewset
    Restful Structure:
        | URL style      | HTTP Method | URL Nanme   | Action Function |
        |----------------|-------------|-------------|-----------------|
        | /users         | GET, POST   | user-list   | user_list       |
        | /users/<email> | GET, DELETE | user-detail | user_detail     |
    """
    # Router class variables
    lookup_field = 'email'
    lookup_value_regex = '[\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}'

    # Viewsets class variables
    #queryset = User.objects.all()

    def list(self, request):
        """GET - Show all users"""
        print request.version
        api_result = user_list.lists_all_users()
        return Response(api_result)

    def create(self, request):
        """POST - Add new user"""
        api_result = user_list.create_new_user(request.data)
        return Response(api_result)

    def retrieve(self, request, email=None):
        """GET - Show <email> user"""
        api_result = user_detail.retrieve_the_user(email)
        return Response(api_result)

    def partial_update(self, request, email=None):
        return Response()

    def destroy(self, request, email=None):
        """DETELE - Delete <email> user"""
        api_result = user_detail.destroy_the_user(email)
        return Response(api_result)

When I finish the UserViewSet containing basic restful api, I register in router:

router = routers.SimpleRouter(trailing_slash=False)
router.register(prefix=r'users', viewset=UserViewSet, base_name='user')

So there will generate with corresponding urls:

  • listand create are with corresponding url: /users
  • retrieve, partial_update and destroy are with corresponding url: /users/<email>

Suppose you need to add more customize urls, you should use list_route or detail_route to expand the viewset:

@list_route(methods=['post'])
def login(self, request):
    """POST - login by user"""
    ...

So the new action is with corresponding url:

  • loginis with corresponding url: /users/login

I hope it can help you.

10👍

You can add more endpoints to a default router by using @detail_route or @list_route decorators on views.

@list_route will create a new endpoint on /myModel/new-route/, whereas @detail_route will create new endpoint on /myModel/<id-of-model>/new-route/

However if you want to completely replace the endpoints provided by Default router, you should think about writing a custom router.

DRF’s documentation has good explanation of custom router as well as a sample custom router as example is there.

👤iankit

Leave a comment