【问题标题】:How do I Delete related resources with TastyPie如何使用 TastyPie 删除相关资源
【发布时间】:2013-12-26 19:49:32
【问题描述】:

我有两个相关的资源:

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 对象,但这不会发生。同样,如果我列出一个不包含现有值的数量列表,我希望它会被删除。

【问题讨论】:

    标签: django rest tastypie


    【解决方案1】:

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

    处理此问题的最佳方法可能是启用对 QuantityResrouce 和 PUT 更新列表的过滤,以过滤由父资源过滤的数量资源,这将添加/更新/删除集合中的所有内容。请注意,您必须将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)
    

    【讨论】:

    • 之前没有对列表端点执行 PUT。我会试一试。
    • 两年前的补丁看起来很完美,我只是把它放到了 ModelResource 的本地子类中。像冠军一样工作!
    猜你喜欢
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    相关资源
    最近更新 更多