关于python:on_delete在Django模型上做了什么?

what does on_delete do on Django models?

我对Django很熟悉,但最近注意到有一个on_delete=models.CASCADE选项,我已经搜索了相同的文档,但除了:

Changed in Django 1.9:

on_delete can now be used as the second positional argument (previously it was typically only passed as a keyword argument). It will be a required argument in Django 2.0.

使用的一个例子是

1
2
3
4
5
6
7
8
9
10
11
12
from django.db import models

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

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

删除时做什么?(如果模型被删除,我想应该做些什么)

models.CASCADE是做什么的?(文档中的任何提示)

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

文件存放在哪里?


这是删除引用对象时要采用的行为。它不是特定于Django的,这是一个SQL标准。

当此类事件发生时,有6种可能采取的措施:

  • CASCADE:删除被引用对象时,也要删除引用它的对象(例如删除博客文章时,也可能要删除注释)。SQL等价物:CASCADE
  • PROTECT:禁止删除被引用对象。要删除它,您必须删除手动引用它的所有对象。SQL等价物:RESTRICT
  • SET_NULL:将引用设置为空(要求字段可以为空)。例如,当您删除一个用户时,您可能希望保留他在博客文章中发布的评论,但要说它是由匿名(或已删除)用户发布的。SQL等价物:SET NULL
  • SET_DEFAULT:设置默认值。SQL等价物:SET DEFAULT
  • SET(...):设置给定值。这不是SQL标准的一部分,完全由Django处理。
  • DO_NOTHING:这可能是一个非常糟糕的主意,因为这会在数据库中创建完整性问题(引用一个实际上不存在的对象)。SQL等价物:NO ACTION

资料来源:Django文件

例如,请参见PostgreSQL的文档。

在大多数情况下,CASCADE是预期行为,但对于每个foreignkey,您应该总是问自己在这种情况下预期的行为是什么。PROTECTSET_NULL通常是有用的。将CASCADE设置为不应该的位置,只需删除一个用户,就可以潜在地级联删除所有数据库。


on_delete方法用于告诉django如何处理依赖于您删除的模型实例的模型实例。(例如,ForeignKey关系)。on_delete=models.CASCADE告诉django级联删除效果,即继续删除依赖模型。

下面是一个更具体的例子。假设您有一个Author模型,它是Book模型中的ForeignKey。现在,如果删除Author模型的实例,django将不知道如何处理依赖Author模型实例的Book模型实例。on_delete方法告诉django在这种情况下应该做什么。设置on_delete=models.CASCADE将指示django级联删除效果,即删除依赖于删除的Author模型实例的所有Book模型实例。

注:on_delete将成为django 2.0中的必选项。在旧版本中,它默认为CASCADE

这是完整的官方文件。


仅供参考,模型中的on-delete参数与听起来的相反。在模型的外键(fk)上加上"on-delete",告诉Django如果删除了记录上指向的fk条目,该怎么做。我们商店使用最多的选项是保护、层叠和设置为空。以下是我所理解的基本规则:

  • 当您的fk指向一个查找表时,使用protect,该查找表确实不应该被更改,而且肯定不会导致您的表发生更改。如果有人试图删除该查找表上的某个条目,则如果该条目绑定到任何记录,则保护将阻止他们删除该条目。它还防止Django删除您的记录,因为它删除了查找表上的一个条目。最后一部分很关键。如果有人要从我的性别表中删除性别"女性",我当然不想立即删除我的个人表中所有拥有该性别的人。
  • 当FK指向"父"记录时,使用"层叠"。所以,如果一个人可以有许多个人种族条目(他/她可以是美国印第安人、黑人和白人),并且该人被删除,我真的希望删除任何"儿童"个人种族条目。没有这个人,他们是不相干的。
  • 当您确实希望允许人们删除查找表上的条目,但您仍然希望保留您的记录时,请使用set_null。例如,如果一个人可以拥有一所高中,但如果那所高中在我的查找表上消失对我来说并不重要,我会说"on delete=set null"。这会使我的个人记录留在那里;它只会将我的个人的高中FK设置为空。很明显,在那个fk上必须允许空=真。
  • 下面是一个模型的例子,它可以完成所有三件事情:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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'

    最后一点,您知道如果您不指定删除(或不指定),默认行为是级联的吗?这意味着,如果有人删除了性别表中的性别条目,则具有该性别的任何个人记录也将被删除!

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

    另外,值得注意的是,如果您选择的行为是这样的,那么在"删除=层叠"上实际上不会添加到任何迁移中。我想这是因为它是默认设置,所以设置_Delete=cascade与不设置是一样的。


    这里是你的问题,回答说:"为什么我们使用在线_删除?P></

    当安在外键是消去referenced模式对象,Django默认行为模式仿效the of the SQL DELETE级联网络约束和外键对象也deletes茶含茶。这种行为模式的overridden can be the argument specifying在线_删除。for example,if You have a null外键和你想集恩to be when the referenced消去对象是零:P></

    1
    user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)

    _ values for the possible在线:在django.db.models删除are foundP></

    级联:级联deletes;the默认。P></

    保护:防止通过删除模式对象protectederror referenced of the,of django.db.integrityerror subclass。P></

    集集_ null外键:this is only possible if空;空是真的。P></

    集集_ to its外键:默认默认默认值;must be for the外键的集合。P></


    作为上述earlier级联删除记录,将that has key和一个面向国外,deleted references。我知道如果你有一个example for real property and have a website,夏天在市referencesP></

    1
    2
    3
    4
    5
    6
    class City(models.Model):
        # define model fields for a city

    class Property(models.Model):
        city = models.ForeignKey(City, on_delete = models.CASCADE)
        # define model fields for a property

    现在市is when the消去from the properties(EG相关的数据库,在夏天,并置。在马德里市也会消去)be from the数据库P></

    现在我也关注其他期权拉提of the such as,集集_ _空或默认或任何_什么给你。基本上,从管理的角度,你想要记录那些"删除"。但我真的希望你不要them to滚开。for many的原因。有人可能有恩accidentally消去,or for审计和监控。报告和平原。我知道它可以在路的"断开"the property from a市。再次,它会depend how is written的在线应用。P></

    some applications for example,有一场"消去"which is 0或1。在列表视图和与他们searches anything that can等,出现在the user can reports or EN * from the前端接入,that is deleted == 1拒绝什么。不管一个人多,如果你在创建自定义查询自定义报告或记录在list of Down to pull that是消去偶知道和看到更多的,当它修饰(最后一场)和模式(即WHO:谁当消去)..that is from the standpoint甚有利于执行。P></

    *不要忘了,你可以简单deleted = 0原accidental deletions as for那些记录。P></

    我点的是,if there is there is a reason,功能性,它总是在背后。总是不好的原因。but a reason。和一个太好的政治家。P></