在django-tastypie中嵌套ToManyFields

时间:2012-02-20 07:14:33

标签: django tastypie

我有两个ModelResourceAttackPacket,与ManyToManyField相关。

这往往会显示Packet.attacks包含1-3次攻击,Attack.packets包含数百个数据包。

我计划这样做的方式是:每个AttackResource都有一个Attack.packets属性,该属性是包含Attack.packets的查询集的链接,以及查询集嵌套的位置在AttackResource

即:

/api/attack/1/ # contains attribute with URL of /api/attack/1/packets/
/api/attack/1/packets/ # contains all packets where attack with id=1 is in Packet.attacks

我该怎么做?

我尝试跟随cyberdelia's gist拥有嵌套资源,但转到/api/attack/1/packets/实际上并不包含attack.id在packet.attacks中的数据包。

我的ModelResource课程与要点相同,然后我的其他资源是:

class AttackResource(ModelResource):
    packets = fields.ToManyField('honeywall.api.PacketResource', 'packets', 'attack')

    class Meta:
        queryset = Attack.objects.all()
        resource_name = 'attack'

class PacketResource(ModelResource):
    attacks = fields.ToManyField('honeywall.api.AttackResource', 'attacks', 'packet')

    class Meta:
        queryset = Packet.objects.all()
        resource_name = 'packet'
        filtering = {
            'attacks': ALL_WITH_RELATIONS,
        }

2 个答案:

答案 0 :(得分:1)

将此添加到AttackResource:

def prepend_urls(self):
    return [
        url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/packets%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_attacks'), name="api_get_attacks"),
    ]

def get_attacks(self, request, **kwargs):
    try:
        bundle = self.build_bundle(data={'pk': kwargs['pk']}, request=request)
        obj = self.cached_obj_get(bundle=bundle, **self.remove_api_resource_names(kwargs))
    except ObjectDoesNotExist:
        return HttpGone()
    except MultipleObjectsReturned:
        return HttpMultipleChoices("More than one resource is found at this URI.")

    attack_resource = AttackResource()
    return attack_resource.get_detail(request, id=obj.pk)

答案 1 :(得分:0)

您可以通过覆盖资源中的override_urls函数来创建嵌套资源。 一种方法可以在tastypie documentation中找到。它基于在您的资源中创建一个将获得所有子项的自定义函数,并且您需要为每个资源编写此函数。

如果这对您来说效果不好,那么还有其他方法可以做到这一点。更通用的方法,它适用于所有嵌套资源,无需编写任何其他功能。它可以在gist上找到。