Django在删除时将外键设置为父值

时间:2017-05-08 21:59:22

标签: django postgresql django-models django-orm

我有一个带有自引用外键的模型Location。删除位置的父级后,我想将其parent_id设置为其祖父母的ID,但不出所料,以下内容会引发错误name 'parent' is not defined

class Location(Model):
    parent = models.ForeignKey('self', models.SET(parent))

如果我要从此表中删除Colorado

| id | name     | parent_id |
|----|----------|-----------|
| 1  | USA      | NULL      |
| 2  | Canada   | NULL      |
| 3  | Colorado | 1         |
| 4  | Utah     | 1         |
| 5  | Denver   | 3         |
| 6  | Boulder  | 3         |

我希望结果看起来像这样:

| id | name     | parent_id |
|----|----------|-----------|
| 1  | USA      | NULL      |
| 2  | Canada   | NULL      |
| 4  | Utah     | 1         |
| 5  | Denver   | 1         |
| 6  | Boulder  | 1         |

2 个答案:

答案 0 :(得分:0)

是的,错误是预期的,models.SET可以采取可调用但它不接受参数因此问题仍然存在,因为我们无法访问被删除的对象,您尝试实现的内容可以由{处理{3}}信号:

from django.dispatch.dispatcher import receiver
from django.db.models.signals import post_delete


@receiver(post_delete, sender=Location,
          dispatch_uid='some.unique.string.id.for.location.delete')
def location_post_delete_handler(sender, instance, **kwargs):
    parent = instance.parent
    Location.objects.filter(parent_id=instance.id).update(parent=parent)

答案 1 :(得分:0)

Aamir Adnan 的回答对我不起作用,因为在 post_delete 信号时刻实例已经没有 id 属性(我猜)。所以我使用了 pre_delete

# when a category is deleted, switchs its childrens parent attr to its own parent (or None)
@receiver(pre_delete,
          sender=Category,
          dispatch_uid='delete_category')
def category_post_delete_handler(sender, instance, **kwargs):
    new_parent = instance.parent if instance.parent else None
    Category.objects.filter(parent_id=instance.id).update(parent=new_parent)

我还必须将 on_delete 设置为 DO_NOTHING,这样它就不会丢弃 pre_delete 刚刚所做的更改。

parent = models.ForeignKey('self',
          on_delete=models.DO_NOTHING, # handled via Category's pre_delete signal
          verbose_name=_('parent'),
          related_name='child_categories',
          blank=True,
          null=True)