Multiple View Django Rest Framework Routers

I am trying to create an API using DRF 3.1. I started by creating manangement functions using ModelViewSet and registering them using DefaultRouter. This worked fine, and in the root API view, corresponding links were created by default when viewed in a browser. Then I created more limited view types for standard users using ReadOnlyModelViewSet, there was a problem when I tried to register these limited views using a router, because ReadOnlyModelViewSets seems to be rewriting links in the root view of the API. The generated URLs seem to work when typed into the browser, but the links in the root view of the API 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 creates a default root API look like this

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

while what I'm looking for is

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

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

any help would be greatly appreciated

+6
source share
2 answers

I had the same problem and, fortunately, found a solution.

Extend your urls.py as follows:

 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 :)

+6
source

The answer from Dario Beringer is correct. But this is not just magic.

The important part is adding an explicit base_name . Usually DRF automatically generates base_name from your request. This is explained here under "base_name": www.django-rest-framework.org/api-guide/routers/. The set of AdminUnitViewSet and UserUnitViewSet is internal.

This causes the later registered ViewSet overwrite the previously registered ViewSet if there is no explicit new registered base_name .

base_name is responsible for creating the named URL in Django. If there is more than one named URL with the same name, Django will basically only consider the latter: https://docs.djangoproject.com/en/1.10/topics/http/urls/#naming-url-patterns

Basically the same issue that was discussed in the Django Rest Framework with multiple environments and routers for the same object

0
source

Source: https://habr.com/ru/post/988180/


All Articles