用相关 objects 扩展 tastypie API

Extending tastypie API with related objects

我是 Django 的新手,Tastypie 在这里提问。

我有一个使用 Tastypie 的 API 的 Django 应用程序。如果我向 /api/v1/ou/33/ 发出 GET 请求,我的 API returns id==33 的 object 没问题。

{
  "child_ou_uri": "/api/v1/ou/33/child_ou/",
  "displayname": "Mother",
  "id": 33,
  "inherit": true,
  "name": "Mother",
  "resource_uri": "/api/v1/ou/33/"
}

问题是,我正在尝试扩展 API 以便它 returns 通过上面 [=50] 中的 child_ou_uri URI 与 object 相关=]. children 与他们的 parents 是同一类型的 objects。该模型有一个属性 parent_id 指向其 parent 的 pk

我的 OuResource 看起来像这样:

class OuResource(ModelResource):

    class Meta:
        queryset = OU.objects.all()
        resource_name = 'ou'
        list_allowed_methods = ['get']
        detail_allowed_methods = ['get']
        filtering = {
            'name': ['icontains'],
        }

        authentication = SessionAuthentication()
        authorization = OperatorLocationAuthorization()

    def get_child_ou(self, request, **kwargs):
        self.method_check(request, ['get', ])

        ous = OuResource().get_list(request, parent_id=kwargs['pk'])

        return ous

    def prepend_urls(self):

        return [
            url(r'^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/child_ou%s$' % (self._meta.resource_name, '/'),
            self.wrap_view('get_child_ou'),
            name='api_get_child_ou')
        ]

    def dehydrate(self, bundle):
        kwargs = dict(api_name='v1', resource_name=self._meta.resource_name, pk=bundle.data['id'])

        bundle.data['child_ou_uri'] = reverse('api_get_child_ou', kwargs=kwargs)

        return bundle

当我导航到 /api/v1/ou/33/child_ou/ 时,我想获取 child object 的列表,它们的属性 parent_id 设置为 33,但是我获取我所有的 object 完全没有任何过滤,相当于我导航到 /api/v1/ou/

{
  "meta": {
    "limit": 20,
    "next": "/api/v1/ou/?offset=20&limit=20&format=json",
    "offset": 0,
    "previous": null,
    "total_count": 29
  },
  "objects": [
    {
      "child_ou_uri": "/api/v1/ou/33/child_ou/",
      "displayname": "Mother",
      "id": 33,
      "inherit": true,
      "name": "Mother",
      "resource_uri": "/api/v1/ou/33/"
    },
    {
      "child_ou_uri": "/api/v1/ou/57/child_ou/",
      "displayname": "Mothers 1st child",
      "id": 57,
      "inherit": true,
      "name": "Child 1",
      "resource_uri": "/api/v1/ou/57/"
    },
    {
      "child_ou_uri": "/api/v1/ou/58/child_ou/",
      "displayname": "Mothers 2nd child",
      "id": 58,
      "inherit": true,
      "name": "Child 2",
      "resource_uri": "/api/v1/ou/58/"
    }
  ]
}

我在这里错过了什么?

[解决方案]

Gareth 的回答让我走上了正轨。我将我的 OuResource 更改为如下所示。这使我可以导航到 url,例如 /api/v1/ou/33/child_ous/,其中 returns 是 child object 的自定义 json。

class OuResource(ModelResource):
    class Meta:
        queryset = OU.objects.all()
        resource_name = 'ou'
        list_allowed_methods = ['get']
        detail_allowed_methods = ['get']
        filtering = {
            'name': ['icontains'],
        }

        authentication = SessionAuthentication()
        authorization = OperatorLocationAuthorization()

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/(?P<ou_id>\d+)/child_ous%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('child_ous'), name="api_child_ous"),
        ]

    def child_ous(self, request, **kwargs):
        self.method_check(request, allowed=['get'])
        self.is_authenticated(request)
        self.throttle_check(request)

        ous = list(OU.objects.filter(parent_id=kwargs['ou_id']))

        data = []
        for x in ous:
            data.append({
                'id' : x.id,
                'name' : x.name,
                'parent_id' : x.parent_id
            })

        return JsonResponse(data, safe=False)

首先,查看 creating a search 上的 tastypie 文档。

如果不嵌套,这样做会更容易,例如/api/v1/ou_related/?to=58,但为了表现力,可能需要嵌套。

对于带分页的嵌套搜索,请查看创建另一个资源 OuSearchResource。该资源将 override authorized_read_list(可能 get_list)传递必要的详细信息。