如何建立一个Django的REST的API返回的车型自定义列表? [英] How to build a Django REST-Api that returns a custom list of models?

查看:136
本文介绍了如何建立一个Django的REST的API返回的车型自定义列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在试图建立一个使用的Django的REST框架我的API带来很大的麻烦。我一直停留在同一个问题,现在好几天。我尝试过多种解决方案和code-片段,问人,但无济于事充足。我试着按照该文档的所有指令,但对我来说他们是不清楚,不完整的。所以,我很绝望清晰,简洁,完整的工作的例子来解决我的问题。

现在,这里是我的问题:

我已经成功地按照说明的 这里 。这些指令使得它很容易建立返回根据用户提供的ID一定的模式,或单一实例的所有实例列表的API。所以,既然我有一个名为MyObject的模式,我已经建立了返回所有当你点击URL / API / myObjects的myObjects列表的API。如果我打的网址/ API / myObjects / 60,它给我的ID == 60 myObject的。到目前为止好!

但我并不想这样做。我想要的东西有点复杂。该模型myObject的有一个方法调用getCustomObjects()。此方法本身返回myObjects的列表。当我打的网址/ API / myObjects / 60,我希望它返回由与ID == 60 myObject的调用getCustomObjects()生成的列表。这个看似简单的变化是造成我来说是非常重要的头痛,我无法弄清楚如何做到这一点。其原因是因为我想返回对象的非标准清单,我不能使用如文档描述了ModelViewSet做事的标准方法。当我做,我认为应该工作的变化,我得到的错误。我现在的错误是: BASE_NAME 如果没有指定,不能自动从视图集确定名称,因为它不具有 .MODEL .queryset 属性。。所有我看过治愈这个错误的文档说,我需要指定一个BASE_NAME的说法。什么BASE_NAME参数的值应该是怎样,我应该在我的网址使用它非常清楚我。我没有一个很好的解释。这就是为什么我张贴我的完整code。如果有人能清楚完整地告诉我如何解决它,我将非常感激。

我的路线是这样的对myApp的url.py:

 从rest_framework进口路由器
路由器= routers.DefaultRouter()router.register(r'myObjects /(P<&ID GT;?\\ d +)/ $',views.MyObjectsViewSet)
URL(R'^ API /',包括:(router.urls))

我的模型是这样的:

 类为MyObject(models.Model):
    名称= models.TextField()

我的串行器看起来是这样的:

 类MyObjectSerializer(serializers.HyperlinkedModelSerializer):
    类元:
        模型=为MyObject
    栏=('身份证','名',)

我的视图集是这样的:

 类MyObjectsViewSet(viewsets.ViewSet):    高清检索(个体经营,请求,PK =无):
        查询集= MyObjects.objects.get(PK = PK).customMyObjectList()        如果没有查询集:
            返回响应(状态= status.HTTP_400_BAD_REQUEST)
        其他:
            串行= MyObjectSerializer(查询集)
            返回响应(serializer.data,状态= status.HTTP_200_OK)

当我打到/ API / myObjects / 60 /我得到以下错误:

 `base_name`如果没有指定,不能自动从视图集确定名称,因为它没有一个`.model`或`.queryset`属性。


解决方案

BASE_NAME 用来让路由器能正确地命名网址

。您所使用的defaultrouter中使用视图组的模型或查询集属性。但是,由于您使用的是viewsets.ViewSet其中既没有,路由器不能确定用于命名生成的URL模式的基本名称(例如,'MyObject的细节或MyObject的列表')

  router.register(r'myObjects',views.MyObjectsViewSet,BASE_NAME ='为MyObject')

这将导致创建以下URL模式: ^ myObjects / {PK} / $ 名为:'为MyObject细节

注意,第一个参数注册必须 r'myObjects 不是 r'myObjects /(P< ID> \\ D +)/? $ 因为路由器只需要preFIX并采取创建模式的照顾。总之,这是从DRF文档的摘录


  

有两个强制性参数寄存器()方法:


  
  

    

preFIX - 网址preFIX用于该组的路线


    
    

视图集 - 该视图集类


  
  
  

另外,您也可以指定一个额外的参数:


  
  

BASE_NAME - 该基地用于所创建的URL的名称。如果未设置
  基名称会自动生成基于模型
  或查询集属性的视图集,如果它有一个。请注意,如果视图集不包括模型或查询集属性,那么你必须在注册时视图集中设置BASE_NAME。


请参阅路由器文档: www.django-rest-framework.org/api-指南/路由器

I'm having a great deal of trouble trying build my API using the Django Rest Framework. I have been stuck on the same issue now for several days. I've tried numerous solutions and code-snippets and asked plenty of people but to no avail. I've tried to follow all the instructions in the docs, but to me they are unclear and incomplete. So I'm very desperate for a clear, concise, complete working example to solve me problem.

Now here is my question:

I have been successful at building a simple Django Rest API by following the instructions here. These instructions make it very easy to build an API that returns a list of all instances of a certain model, or a single instance based on a user-provided ID. So, since I have a model named MyObject, I have built an api that returns a list of all the myObjects when you hit the URL /api/myObjects. If I hit the URL /api/myObjects/60, it gives me the myObject with ID==60. So far so good!

But I don't want to do this. I want something a bit more complex. The myObject model has a method called getCustomObjects(). This method itself returns a list of myObjects. When I hit the URL /api/myObjects/60, I want it to return the list produced by calling getCustomObjects() on the myObject with ID==60. This seemingly simple change is causing me a very major headache and I can't figure out how to do it. The reason is that because I want to return a non-standard list of objects, I cannot use the standard way of doing things with a ModelViewSet as described in the docs. When I make the changes that I think should work, I get errors. My current error is: base_name argument not specified, and could not automatically determine the name from the viewset, as it does not have a .model or .queryset attribute.. All the docs I have read to cure this error say that I need to specify a "base_name" argument. What the value of that base_name argument should be and how I should use it in my URL are very unclear to me. I don't have a good explanation. That's why I'm posting my complete code. If someone can advise me clearly and completely how to fix it, I would be very grateful.

My Route looks like this in myApp's 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)),

My Model looks like this:

class MyObject(models.Model):
    name = models.TextField()

My Serializer looks like this:

class MyObjectSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyObject
    fields = ('id', 'name',)

My Viewset looks like this:

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)

When I hit /api/myObjects/60/ I get the following error:

`base_name` argument not specified, and could not automatically determine the name from the viewset, as it does not have a `.model` or `.queryset` attribute.

解决方案

base_name is used so the router can properly name the URLs. The DefaultRouter you are using uses the model or queryset attributes of the view set. But since you are using viewsets.ViewSet which has neither, the router cannot determine the base name used to name the generated URL patterns (eg, 'myobject-detail' or 'myobject-list')

router.register(r'myObjects', views.MyObjectsViewSet, base_name='myobject')

This will result in creating the following URL pattern: ^myObjects/{pk}/$ with the name: 'myobject-detail'.

Notice the first param to register must be r'myObjects' not r'myObjects/(?P<id>\d+)/?$' because the router just needs the prefix and will take care of creating the patterns. To summarize this is an excerpt from DRF docs

There are two mandatory arguments to the register() method:

prefix - The URL prefix to use for this set of routes.

viewset - The viewset class.

Optionally, you may also specify an additional argument:

base_name - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the model or queryset attribute on the viewset, if it has one. Note that if the viewset does not include a model or queryset attribute then you must set base_name when registering the viewset.

See routers docs: www.django-rest-framework.org/api-guide/routers

这篇关于如何建立一个Django的REST的API返回的车型自定义列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆