简体   繁体   English

Django Rest Framework,具有多个Viewset和Routers,用于同一对象

[英]Django Rest Framework with multiple Viewsets and Routers for the same object

I am having trouble defining different view sets for the same object using Django Rest Framework. 我无法使用Django Rest Framework为同一个对象定义不同的视图集。 Following is a minimal example to reproduce the issue, based on DRF Quickstart. 以下是基于DRF快速入门重现问题的最小示例。 I am using python 3.5 and the latest DRF. 我使用的是python 3.5和最新的DRF。

tutorial/quickstart/serializers.py 教程/快速启动/ 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 教程/快速启动/ 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 教程/ 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/ . 注意usersusers-minimal指向.../users-minimal/

Also, when accessing http://HOST:PORT/users/ you get: 此外,当访问http://HOST:PORT/users/您会得到:

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/ . 请注意,网址指向.../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 to users-minimal : 简短回答:您必须将basename参数添加到您的users-minimal路由users-minimal

router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'users-minimal', UserMinimalViewSet, basename='usersminimal')

Normally DRF genereates a basename automatically from your queryset . 通常DRF genereates一个basename从你的自动queryset This is explained in the DRF routers docs , search for basename . 这在DRF路由器文档中进行了解释,搜索了basename

Your two Viewset s use the same queryset so the have initially the same basename . 你的两个Viewset的使用相同的queryset ,因此最初有相同的basename That leads to the problems which you have seen, that the later registered ViewSet will overwrite the routes from the former registered ViewSet . 这导致您看到的问题,后来注册的ViewSet将覆盖以前注册的ViewSet的路由。 You can see this in action when you change the order of the router.register in your example. 在更改示例中router.register的顺序时,您可以看到此操作。

You can see the base names of your routes when you test the code directly in the shell: 在shell中直接测试代码时,可以看到路由的基本名称:

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)


> routers.urls
[<RegexURLPattern user-list ^minimal/$>,
<RegexURLPattern user-list ^minimal\.(?P<format>[a-z0-9]+)/?$>,
<RegexURLPattern user-detail ^minimal/(?P<pk>[^/.]+)/$>,
<RegexURLPattern user-detail ^minimal/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$>,
<RegexURLPattern user-list ^users/$>,
<RegexURLPattern user-list ^users\.(?P<format>[a-z0-9]+)/?$>,
<RegexURLPattern user-detail ^users/(?P<pk>[^/.]+)/$>,
<RegexURLPattern user-detail ^users/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$>,
<RegexURLPattern api-root ^$>,
<RegexURLPattern api-root ^\.(?P<format>[a-z0-9]+)/?$>]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM