我很熟悉Django,但我最近注意到存在一个on_delete=models。级联选项与模型。我已经搜索了相同的文档,但我找不到更多的东西:

在Django 1.9中更改: On_delete现在可以用作第二个位置参数(以前它通常只作为关键字参数传递)。它将是Django 2.0中必须的参数。

用法示例如下:

from django.db import models

class Car(models.Model):
    manufacturer = models.ForeignKey(
        'Manufacturer',
        on_delete=models.CASCADE,
    )
    # ...

class Manufacturer(models.Model):
    # ...
    pass

on_delete做什么?(我猜如果模型被删除了要做的动作。)

什么是模型。级联做什么?(文档中的提示)

还有什么其他的选择(如果我的猜测是正确的)?

这方面的文档放在哪里?


当前回答

简单地说,on_delete是一条指令,用于指定在删除外部对象时将对对象进行哪些修改:

CASCADE:当外部对象被删除时,将删除子对象

SET_NULL:将子对象外键设置为null

SET_DEFAULT:在创建模型时将子对象设置为给定的默认数据

RESTRICT:在某些条件下引发RestrictedError。

PROTECT:防止外部对象被删除,只要有子对象从它继承

额外的链接:

https://docs.djangoproject.com/en/4.0/ref/models/fields/#foreignkey

其他回答

重新定位你对“CASCADE”功能的思维模式,将FK添加到一个已经存在的CASCADE(即瀑布)中。这个瀑布的源是一个主键(PK)。删除向下流动。

因此,如果您将一个FK的on_delete定义为“CASCADE”,那么您将把这个FK的记录添加到一个源于PK的级联删除中。FK的记录可能参与这个级联,也可能不参与(“SET_NULL”)。事实上,具有FK的记录甚至可能阻止删除流!用“PROTECT”建造一座大坝。

供您参考,模型中的on_delete参数与它听起来的相反。你把on_delete放在一个模型的外键(FK)上,告诉Django如果你在记录上指向的FK条目被删除了该怎么办。我们商店使用最多的选项是PROTECT、CASCADE和SET_NULL。以下是我总结出的基本规则:

Use PROTECT when your FK is pointing to a look-up table that really shouldn't be changing and that certainly should not cause your table to change. If anyone tries to delete an entry on that look-up table, PROTECT prevents them from deleting it if it is tied to any records. It also prevents Django from deleting your record just because it deleted an entry on a look-up table. This last part is critical. If someone were to delete the gender "Female" from my Gender table, I CERTAINLY would NOT want that to instantly delete any and all people I had in my Person table who had that gender. Use CASCADE when your FK is pointing to a "parent" record. So, if a Person can have many PersonEthnicity entries (he/she can be American Indian, Black, and White), and that Person is deleted, I really would want any "child" PersonEthnicity entries to be deleted. They are irrelevant without the Person. Use SET_NULL when you do want people to be allowed to delete an entry on a look-up table, but you still want to preserve your record. For example, if a Person can have a HighSchool, but it doesn't really matter to me if that high-school goes away on my look-up table, I would say on_delete=SET_NULL. This would leave my Person record out there; it just would just set the high-school FK on my Person to null. Obviously, you will have to allow null=True on that FK.

下面是一个模型的例子,它可以做到这三件事:

class PurchPurchaseAccount(models.Model):
    id = models.AutoField(primary_key=True)
    purchase = models.ForeignKey(PurchPurchase, null=True, db_column='purchase', blank=True, on_delete=models.CASCADE) # If "parent" rec gone, delete "child" rec!!!
    paid_from_acct = models.ForeignKey(PurchPaidFromAcct, null=True, db_column='paid_from_acct', blank=True, on_delete=models.PROTECT) # Disallow lookup deletion & do not delete this rec.
    _updated = models.DateTimeField()
    _updatedby = models.ForeignKey(Person, null=True, db_column='_updatedby', blank=True, related_name='acctupdated_by', on_delete=models.SET_NULL) # Person records shouldn't be deleted, but if they are, preserve this PurchPurchaseAccount entry, and just set this person to null.

    def __unicode__(self):
        return str(self.paid_from_acct.display)
    class Meta:
        db_table = u'purch_purchase_account'

作为最后的花边新闻,您知道如果您没有指定on_delete(或没有指定),默认行为是CASCADE吗?这意味着如果有人删除了您的gender表中的一个性别条目,那么具有该性别的任何Person记录也会被删除!

我会说,“如果有疑问,设置on_delete=models.PROTECT。”然后测试你的应用程序。您将很快发现哪些fk应该标记为其他值,而不会危及任何数据。

此外,值得注意的是,on_delete=CASCADE实际上没有添加到任何迁移中,如果这是您选择的行为的话。我想这是因为它是默认的,所以把on_delete=CASCADE等同于什么都不放。

假设您有两个模型,一个名为Person,另一个名为Companies。

根据定义,一个人可以创建多家公司。

考虑到一个公司可以有且只能有一个人,我们希望当一个人被删除时,与他相关的所有公司也都被删除。

我们首先创建一个Person模型,像这样

class Person(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.id+self.name

然后,Companies模型看起来像这样

class Companies(models.Model):
    title = models.CharField(max_length=20)
    description=models.CharField(max_length=10)
    person= models.ForeignKey(Person,related_name='persons',on_delete=models.CASCADE)

注意on_delete=models的用法。模型公司中的CASCADE。也就是说,当拥有公司的人(类person的实例)被删除时,删除所有公司。

删除父对象时删除数据库中的所有子字段,然后使用on_delete,如下所示:

class user(models.Model):
    commodities = models.ForeignKey(commodity, on_delete=models.CASCADE)

CASCADE也会删除与之相连的对应字段。