我的路由中需要什么base_name参数才能使这个Django API工作?

Saq*_*Ali 31 python django rest

我正在构建一个Django应用程序,它公开了一个REST API,用户可以通过它查询我的应用程序的模型.我按照这里的说明操作.

我的路线在myApp的url.py中看起来像这样:

from rest_framework import routers
router = routers.DefaultRouter()    router.register(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsViewSet)
url(r'^api/', include(router.urls)),
Run Code Online (Sandbox Code Playgroud)

我的模型看起来像这样:

class MyObject(models.Model):
    name = models.TextField()
Run Code Online (Sandbox Code Playgroud)

我的Serializer看起来像这样:

class MyObjectSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyObject
    fields = ('id', 'name',)
Run Code Online (Sandbox Code Playgroud)

我的Viewset看起来像这样:

class MyObjectsViewSet(viewsets.ViewSet):

    def retrieve(self,request,pk=None):
        queryset = MyObjects.objects.get(pk=pk).customMyObjectList()

        if not queryset:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        else:
            serializer = MyObjectSerializer(queryset)
            return Response(serializer.data,status=status.HTTP_200_OK)
Run Code Online (Sandbox Code Playgroud)

当我点击/ api/myObjects/60 /时出现以下错误:

base_name参数未指定,并且无法自动确定视图集中的名称,因为它没有.model.queryset属性.

我从这里了解到我的路线上需要一个base_name参数.但是从文档来看,我不清楚base_name参数的值应该是什么.有人可以告诉我base_name的路径应该是什么样的?

Eri*_*Lee 43

尝试在urls.py中执行此操作.第三个参数'Person'可以是你想要的任何东西.

router.register(r'person/food', views.PersonViewSet, 'Person')
Run Code Online (Sandbox Code Playgroud)

  • @EricLee你能解释一下为什么会这样吗?谢谢 (18认同)
  • @palafox_e 默认路由器使用序列化程序中定义的查询集来确定基本名称。basename 指定路由器生成的 url 的开头。如果 queryset 没有设置为 ViewSet 属性,则路由器会举手抗议,而不会尝试在函数中找到 queryset。指定 'Person' 意味着内部 view_name's 将以 'Person' 开头,但 url 仍然由第一个参数指定 更多信息请查看:http://www.django-rest-framework.org/api-guide/routers /#用法 (3认同)
  • 这个答案没有解释任何事情 (2认同)

小智 13

也许你只需要base_name为你的路由器设置参数的名称:MyObject在你的情况下.

router.register(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsViewSet, base_name="MyObject")
Run Code Online (Sandbox Code Playgroud)

http://www.django-rest-framework.org/api-guide/routers/#Usage


Sri*_*ram 10

让我解释一下,为什么我们首先需要一个base_name然后让我们进入base_name的可能值.

如果你使用Django的网址前的休息框架(DRF),你就已经指定它是这样的:

urlpatterns = [
    url(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsListView.as_view(), name='myobject-list'),
    url(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsDetailView.as_view(), name='myobject-detail'),
]
Run Code Online (Sandbox Code Playgroud)

在这里,如果你看到,有一个name参数,用于标识当前命名空间(即app)中的url .

这正是django-rest-framework自动尝试做的事情,因为drf知道视图是列表还是详细信息(因为视图集).它只需要附加一些前缀来区分网址.这就是base_name(前缀)的目的.

在大多数情况下,您可以将URL资源名称指定base_name.在您的情况下,base_name = myobject.DRF将生成base_name + view_type作为名称参数,如myobject_listmyobject_detail.

注意:通常,base_name自动queryset字段(从视图)获取,因为它对于视图集中的所有视图类型都是相同的.但是如果指定get_queryset方法而不是queryset,则可能意味着您对不同的视图类型(如list,detail)有不同的查询集.因此,DRF将要求您为资源的所有视图类型指定公共base_name.


小智 2

另一种解决方案可能是使用 ModelViewSet 它将自动从模型中派生基本名称。

只需确定并告诉它使用哪个模型:

由于 ModelViewSet 扩展了 GenericAPIView,因此您通常需要至少提供 queryset 和 serializer_class 属性,或模型属性快捷方式。

  • 这真的很难而且令人困惑。你能根据我上面的代码告诉我参数base_name应该是什么吗?我不想使用 MovelViewSet 因为我没有使用查询集。我正在通过调用 customMyObjectsList() 来做一些更复杂的事情。 (6认同)