【发布时间】:2012-04-19 07:48:40
【问题描述】:
我有一个一对多的关系,我想在many上的最后一个引用对象之后自动删除one边em> 方已被删除。也就是说,我要进行垃圾回收,或者做一种反向级联操作。
我试图通过使用 Django 的 post_delete 信号来解决这个问题。这是我正在尝试做的一个简化示例:
models.py
class Bar(models.Model):
j = models.IntegerField()
# implicit foo_set
class Foo(models.Model):
i = models.IntegerField()
bar = models.ForeignKey(Bar)
def garbage_collect(sender, instance, **kwargs):
# Bar should be deleted after the last Foo.
if instance.bar.foo_set.count() == 0:
instance.bar.delete()
post_delete.connect(garbage_collect, Foo)
这在使用 Model.delete 时有效,但在使用 QuerySet.delete 时会严重损坏。
tests.py
class TestGarbageCollect(TestCase):
# Bar(j=1)
# Foo(bar=bar, i=1)
# Foo(bar=bar, i=2)
# Foo(bar=bar, i=3)
fixtures = ['db.json']
def test_separate_post_delete(self):
for foo in Foo.objects.all():
foo.delete()
self.assertEqual(Foo.objects.count(), 0)
self.assertEqual(Bar.objects.count(), 0)
这很好用。
tests.py 继续
def test_queryset_post_delete(self):
Foo.objects.all().delete()
self.assertEqual(Foo.objects.count(), 0)
self.assertEqual(Bar.objects.count(), 0)
这会在第二次发出信号时中断,因为正如Django's documentation 所说,QuerySet.delete 会立即应用,而instance.bar.foo_set.count() == 0 在第一次发出信号时就已经为真。仍然从 docs 读取,QuerySet.delete 将为每个已删除的对象发出 post_delete 信号,garbage_collect 在 Bar 被删除后被调用。
接下来的问题:
- 有没有更好的方法来收集 一对多 关系的 one 端?
- 如果不是,我应该更改什么才能使用 QuerySet.delete?
【问题讨论】:
标签: python django garbage-collection django-queryset django-signals