13

I'm using Django Rest Framework's Default Router and try to customize my links.

How do I set arrange something like as the following:

  1. /myModels/dosomething (and get it listed in API Root view)
  2. /myModels/addModel?name=abc&address=xyz

    Views.py

    class MyModelViewSet(viewsets.ModelViewSet):
        queryset = MyModel.objects.all()
        serializer_class = MyModelSerializer
    

    urls.py

    router = routers.DefaultRouter(trailing_slash=True)
    router.register(r'mymodels', views.MyModelViewSet)
    

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Could you clarify what your user_detail and user_list objects refer to?
@list_route(methods=['post']) OUTDATED!!
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.

1 Comment

This was deprecated in DRF 3.8: django-rest-framework.org/community/3.8-announcement/…. You can use an @action decorator instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.