Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework Routers with multiple viewsets

I am attempting to create an API using DRF 3.1. I started by creating manangement functions using ModelViewSet and registering these with a DefaultRouter. This worked perfectly and the default API root view generated the appropriate links when viewed in a browser. I then created more restricted viewsets for standard users using ReadOnlyModelViewSet, the problem occurred when I tried to register these restricted viewsets with the router as the ReadOnlyModelViewSets appear to overwrite the links on the API root view. The generated urls appear to work when typed into the browser but the links on the API root view are not as I expected

serializers.py

class AdminUnitSerializer(serializers.HyperlinkedModelSerializer):
'''
model serializer for admin users containing all fields

'''

url = HyperlinkedIdentityField(view_name='unit-detail')

class Meta:
    model = Unit
    fields = ('url', 'id', 'name', 'symbol', 'converters_from', 'converters_to')

class UserUnitSerializer(serializers.HyperlinkedModelSerializer):
'''
model serializer for standard users containing restricted set of fields

'''

url = HyperlinkedIdentityField(view_name='unit-detail')

class Meta:
    model = Unit
    fields = ('url', 'id', 'name', 'symbol')

views.py

class AdminUnitViewSet(viewsets.ModelViewSet):
'''
simple viewset providing CRUD operations on unit objects

'''

queryset = models.Unit.objects.all()
serializer_class = serializers.AdminUnitSerializer
permission_classes = (permissions.IsAdminUser,)

class UserUnitViewSet(viewsets.ReadOnlyModelViewSet):
'''
read only view set providing list and detail views for unit objects

'''

queryset =  models.Unit.objects.all()
serializer_class = serializers.UserUnitSerializer
permission_classes(permissions.IsAuthenticated,)

urls.py

router.register(r'manangeunits', views.AdminUnitViewSet)
router.register(r'readunits', views.UserUnitViewSet)

urlpatterns = [
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^rest-auth/', include('rest_auth.urls')),
url(r'^', include(router.urls))
]

this produces a default API root view like this

{
"manangeunits": "http://localhost:8000/readunits/",
"readunits": "http://localhost:8000/readunits/",
}

while what I am looking for is this

{
"manangeunits": "htt://localhost:8000/manageunits/",
"readunits": "htt://localhost:8000/readunits/",
}

the url 'htt://localhost:8000/manageunits/' is valid and accessible when the address is typed into the browser it just does not appear on the API root view

any help would be greatly appreciated

like image 881
Mark Davies Avatar asked May 29 '15 15:05

Mark Davies


People also ask

How do you pass extra context data to Serializers in Django REST framework?

In function-based views, we can pass extra context to serializer with “context” parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with “self. context”. From example, to get “exclude_email_list” we just used code 'exclude_email_list = self.

What is difference between APIView and 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 Viewsets Modelviewset?

A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as . get() or . post() , and instead provides actions such as . list() and . create() .

What is routers in Django REST framework?

Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index... a resourceful route declares them in a single line of code.


1 Answers

I had the same issue and luckily found a solution.

Extend your urls.py as following:

router.register(r'manangeunits', views.AdminUnitViewSet, base_name='manangeunits')
router.register(r'readunits', views.UserUnitViewSet, base_name='readunits')

I don't know the magic behind this, but it works for me :)

like image 121
Dario Behringer Avatar answered Oct 17 '22 17:10

Dario Behringer