如何使用TastyPie删除相关资源

时间:2013-12-26 19:49:33

标签: django rest tastypie

我有两个相关的资源:

class QuantityResource(ModelResource):
    class Meta:
        queryset = Quantity.objects.all()

class EntryResource(ModelResource):
    quantities = fields.ToManyField(QuantityResource, 'quantities', full=True, null=True)
    class Meta:
        queryset = Entry.objects.all()

如果我使用quantities: [] PUT到现有条目,我希望TastyPie删除所有相关的Quantity对象,但这不会发生。同样,如果我将列表放入不包含现有值的数量,我希望它会被删除。

1 个答案:

答案 0 :(得分:1)

Tastypie不支持通过多对多关系删除对象。仅支持更新和添加。 Relevant code。它会在您的多对多字段的相关管理器上call clear,但这只会取消您的相关模型与父级的关联,而不会实际删除它们。 2年前有一个patch添加功能,但它从未合并过。

处理此问题的最佳方法可能是将QuantityResroucePUT更新后的列表过滤到由父资源过滤的数量资源,该资源将添加/更新/删除集合中的所有内容。请注意,您必须向ForeignKey添加QuantityResource字段,否则由于数据库限制,您将无法保存集合(假设您需要entry字段Quantity模型。

class QuantityResource(ModelResource):

    entry = fields.ForeignKey('your.resources.EntryResource', 'entry')

    class Meta:
        queryset = Quantity.objects.all()
        filtering = {
            'entry': ['exact'],
        }

这是一个测试用例来说明我的意思:

from tastypie.test import ResourceTestCase

from testres.models import Quantity, Entry


class EntryResourcesTest(ResourceTestCase):

    def setUp(self):
        super(EntryResourcesTest, self).setUp()

        entry = Entry.objects.create(name='Foo')
        entry2 = Entry.objects.create(name='Bar')

        Quantity.objects.create(entry=entry, quantity=1)
        Quantity.objects.create(entry=entry, quantity=3)
        Quantity.objects.create(entry=entry, quantity=5)

        Quantity.objects.create(entry=entry2, quantity=2)

    def test_delete_item(self):
        objs = self.deserialize(
                self.api_client.get('/api/v1/quantity/?entry=1'))['objects'][1:]

        self.assertHttpAccepted(self.api_client.put(
            '/api/v1/quantity/?entry=1', data={ 'objects': objs }))

        # Ensure resource deleted
        obj = self.deserialize(self.api_client.get('/api/v1/entry/1/'))
        self.assertEqual(len(obj['quantities']), 2)

        # Make sure we didn't delete them all
        obj = self.deserialize(self.api_client.get('/api/v1/quantity/'))
        self.assertEqual(len(obj['objects']), 3)