I am having trouble defining different view sets for the same object using Django Rest Framework. Following is a minimal example to reproduce the issue, based on DRF Quickstart. I am using python 3.5 and the latest DRF.
tutorial/quickstart/serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email')
class UserMinimalSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('url', 'username')
tutorial/quickstart/views.py
from django.contrib.auth.models import User
from rest_framework import viewsets
from tutorial.quickstart.serializers import UserSerializer, UserMinimalSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
class UserMinimalViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserMinimalSerializer
tutorial/urls.py
from django.conf.urls import url, include
from rest_framework import routers
from tutorial.quickstart import views
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'users-minimal', views.UserMinimalViewSet)
urlpatterns = [
url(r'^', include(router.urls))
]
When running the server and GETting the root, you end up with:
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"users": "http://127.0.0.1:8000/users-minimal/",
"users-minimal": "http://127.0.0.1:8000/users-minimal/"
}
Note both users
and users-minimal
point to .../users-minimal/
.
Also, when accessing http://HOST:PORT/users/
you get:
HTTP 200 OK
Allow: GET, POST, OPTIONS
Content-Type: application/json
Vary: Accept
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"url": "http://127.0.0.1:8000/users-minimal/2/",
"username": "user2",
"email": "user2@users.com"
},
{
"url": "http://127.0.0.1:8000/users-minimal/1/",
"username": "user1,
"email": "user1@users.com"
}
]
}
Note the urls point to .../users-minimal/
.
Final note: my question is somewhat similar to this one, but the suggested solution did not work for me, nor did it suggest why it should work in the first place.
Short answer: You have to add the
basename
parameter to your route tousers-minimal
:Normally DRF genereates a
basename
automatically from yourqueryset
. This is explained in the DRF routers docs, search forbasename
.Your two
Viewset
s use the samequeryset
so the have initially the samebasename
. That leads to the problems which you have seen, that the later registeredViewSet
will overwrite the routes from the former registeredViewSet
. You can see this in action when you change the order of therouter.register
in your example.You can see the base names of your routes when you test the code directly in the shell: