如何构建一个从URL中提取多个参数的Django REST路由?

时间:2014-03-03 06:50:21

标签: python django rest

我已经为我的应用程序构建了一些Django-Rest-Framework API。这些API执行诸如返回模型实例列表以及返回多少模型满足预定标准的计数。

以下是我的ViewSet的样子:

class MyObjectsViewSet(viewsets.ViewSet):

    def retrieve(self,request,pk=None):
        queryset = ## Do something here to return a list of myObjects
        serializer = MyObjectsSerializer(queryset) ## MyObjectsSerializer not shown here.
        return Response(serializer.data,status=status.HTTP_200_OK)

这就是我的urls.py对于这个端点的看法:

router = routers.DefaultRouter()
router.register(r'myObjects', views.myObjectsViewSet, base_name="myObjects")

urlpatterns = patterns('',
    ...
    url(r'^api/', include(router.urls)),
    ...
)

上面的代码允许我将一个参数带到API并将其用作MyObjectsViewSet.retrieve()中的pk参数。因此,当我将浏览器指向/ api / MyObjects / 60 /时,使用pk == 60调用retrieve()。很棒。一切都很棒。

但现在我需要一个可以做更多事情的API。我需要一个带有两个数字参数(“pk”和“otherArg”)的API,并使用这两个参数调用另一个viewSet(MyObjectsNewView)。因此,当我将浏览器指向/ api / MyObjects / 60/59 /时,将使用参数pk == 60和otherArg == 59调用MyObjectsNewView.retrieve()。

如何在url.py和我的Viewsets中设计我的路线以使其工作?

在其他情况下,当我设计非REST URL时,我使用了regexp并使用这样的符号来指定URL字符串中的提取参数:(?P<MyObjectID>\d+)

看起来我应该能够在这里做同样的事情。但是,如果没有我在路径中的任何地方指定它,它会自动接收pk参数,所以现在我很困惑如何在第一个pk参数sorta神奇地出现而没有任何正则表达式模式时如何为此路由添加另一个参数。

3 个答案:

答案 0 :(得分:4)

Write a custom detail route and change the signature to pass in the additional kwarg you intend to use. Then, customize the url path.

from rest_framework.decorators import detail_route
from rest_framework import viewsets

class MyObjectsViewSet(viewsets.ViewSet):

    @detail_route(methods=['get'], url_path='(?P<oid>\d+)')
    def get_with_objectid(self,request,pk=None, oid=None):
        queryset = ## Do something here with oid to return a list of myObjects
        serializer = MyObjectsSerializer(queryset) ## MyObjectsSerializer not shown here.
        return Response(serializer.data,status=status.HTTP_200_OK)

Now your viewset will work with /api/MyObjects/60/59/ where pk=60 and oid=59. If the url_path was instead url_path='/thisthing/(?P(<oid>\d+)' then the viewset would register /api/MyObjects/60/thisthing/59.

答案 1 :(得分:3)

您可以使用以下模式:

url(r'^resource/(?P<clientId>[A-Za-z0-9]*)/(?P<token>[A-Za-z0-9]*)$', RestResource.as_view()),

RestResource类看起来像这样:

class RestResource(View):
  def put(self, request, clientId, token):
    # Your code here
    return HttpResponse(json.dumps(JSON_DATA_VARIABLE), content_type = "application/json", status = 200)

  def delete(self, request, clientId, token):
    # Your code here
    return HttpResponse(json.dumps(JSON_DATA_VARIABLE), content_type = "application/json", status = 200)

它将接受&#34; PUT&#34;和&#34;删除&#34;请求和路由中定义的参数将在类方法中接收。

希望它可以帮到你, 如果您需要我,我可以获得更多详细信息。

答案 2 :(得分:1)

如果您没有对“pk”和“otherArg”进行严格的验证,则不使用正则表达式 drf 提供带有类型前缀的路径。所以,

第 1 步:在 urlpatters 中,

path('/api/<int:id>/<otherArg>/', YourViewset.action_name, name="action_name")

第 2 步:在视图集中

@action(methods=['get'],detail=True/False)

第 3 步:@action 下面

def action_name(self, id, otherArg):

现在在函数中使用 id, otherArg/s。 进行更改和使用。