Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding more views to a Router or viewset (Django-Rest-Framework)

Essentially, I'm trying to find a good way to attach more views to a Router without creating a custom Router. What's a good way to accomplish this?

Here is something sort of equivalent to what I'm trying to accomplish. Variable names have been changed and the example method I want to introduce is extremely simplified for the sake of this question.

Router:

router = routers.SimpleRouter(trailing_slash=False) router.register(r'myobjects', MyObjectViewSet, base_name='myobjects') urlpatterns = router.urls 

ViewSet

class MyObjectsViewSet(viewsets.ViewSet): """ Provides API Methods to manage MyObjects. """  def list(self, request):     """ Returns a list of MyObjects. """     data = get_list_of_myobjects()     return Response(data)  def retrieve(self, request, pk):     """ Returns a single MyObject. """     data = fetch_my_object(pk)     return Response(data)  def destroy(self, request, pk):     """ Deletes a single MyObject. """     fetch_my_object_and_delete(pk)             return Response() 

One example of another method type I need to include. (There are many of these):

def get_locations(self, request):     """ Returns a list of location objects somehow related to MyObject """     locations = calculate_something()     return Response(locations) 

The end-result is that the following URL would work correctly and be implemented 'cleanly'.

GET example.com/myobjects/123/locations 
like image 481
Kurtis Avatar asked Sep 23 '13 22:09

Kurtis


People also ask

Should I use APIView or Viewset?

APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.

What is difference between View and Viewset in Django?

While regular views act as handlers for HTTP methods, viewsets give you actions, like create or list . The great thing about viewsets is how they make your code consistent and save you from repetition. Every time you write views that should do more than one thing, a viewset is the thing that you want to go for.

What is Viewset in Django REST?

Django REST framework allows you to combine the logic for a set of related views in a single class, called a ViewSet . In other frameworks you may also find conceptually similar implementations named something like 'Resources' or 'Controllers'.

What is Basename in router Django?

basename - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the queryset attribute of the viewset, if it has one. Note that if the viewset does not include a queryset attribute then you must set basename when registering the viewset.


2 Answers

The answer given by mariodev above is correct, as long as you're only looking to make GET requests.

If you want to POST to a function you're appending to a ViewSet, you need to use the action decorator:

from rest_framework.decorators import action, link from rest_framework.response import Response  class MyObjectsViewSet(viewsets.ViewSet):      # For GET Requests     @link()     def get_locations(self, request):         """ Returns a list of location objects somehow related to MyObject """         locations = calculate_something()         return Response(locations)      # For POST Requests     @action()     def update_location(self, request, pk):         """ Updates the object identified by the pk """         location = self.get_object()         location.field = update_location_field() # your custom code         location.save()          # ...create a serializer and return with updated data... 

Then you would POST to a URL formatted like: /myobjects/123/update_location/

http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing has more information if you're interested!

like image 162
piercebot Avatar answered Oct 11 '22 18:10

piercebot


You can now do this with the list_route and detail_route decorators: http://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing

For example:

from rest_framework.decorators import list_route from rest_framework.response import Response ...  class MyObjectsViewSet(viewsets.ViewSet):     ...      @list_route()     def locations(self, request):         queryset = get_locations()         serializer = LocationSerializer(queryset, many=True)         return Response(serializer.data) 
like image 25
seddonym Avatar answered Oct 11 '22 19:10

seddonym