在 Django 模型字段中自定义 `on_delete` 参数函数

124*_*142 3 python django

我有一个 IPv4Manage 模型,其中有一个vlanedipv4network字段:

class IPv4Manage(models.Model):
    ...
    vlanedipv4network = models.ForeignKey(
        to=VlanedIPv4Network, related_name="ipv4s", on_delete=models.xxx, null=True)
Run Code Online (Sandbox Code Playgroud)

众所周知,在on_deleteparam 上,我们一般会填充models.xxx,例如models.CASCADE。

是否可以自定义一个函数,在那里填充?我想在那里做其他逻辑事情。

A. *_*arr 5

的选择on_delete可以在django/db/models/deletion.py

例如,models.SET_NULL 实现为:

def SET_NULL(collector, field, sub_objs, using):
    collector.add_field_update(field, None, sub_objs)
Run Code Online (Sandbox Code Playgroud)

而models.CASCADE(稍微复杂一点)被实现为:

def CASCADE(collector, field, sub_objs, using):
    collector.collect(sub_objs, source=field.remote_field.model,
                      source_attr=field.name, nullable=field.null)
    if field.null and not connections[using].features.can_defer_constraint_checks:
        collector.add_field_update(field, None, sub_objs)
Run Code Online (Sandbox Code Playgroud)

因此,如果您弄清楚这些参数是什么,那么您应该能够定义自己的函数以传递给on_delete模型字段的参数。 collector很可能是Collector(在同一文件中定义的,不确定它的确切用途)的实例,field很可能是模型字段被删除,sub_objs很可能是该字段与对象相关的实例,并using表示正在使用的数据库。

也有用于删除的自定义逻辑的替代方案,以防覆盖 on_delete 对您来说可能有点矫枉过正。

该post_delete和pre_delete允许你之前或实例被删除后,定义一些自定义的逻辑来运行。

from django.db.models.signals import post_save
def delete_ipv4manage(sender, instance, using):
    print('{instance} was deleted'.format(instance=str(instance)))

post_delete.connect(delete_ipv4manage, sender=IPv4Manage)
Run Code Online (Sandbox Code Playgroud)

最后,您可以覆盖delete()Model/Queryset的方法,但是请注意使用此方法进行批量删除的注意事项:

批量操作不会调用覆盖的模型方法

请注意,当使用 QuerySet 批量删除对象或作为级联删除的结果时,不一定会调用对象的 delete() 方法。为确保执行自定义删除逻辑,您可以使用 pre_delete 和/或 post_delete 信号。


Mag*_*AMP 5

另一个有用的解决方案是使用models.SET()你可以传递函数的地方(下面例子中的deleted_guest)

来宾 = models.ForeignKey('来宾', on_delete=models.SET(deleted_guest))

和功能deleted_guest是

DELETED_GUEST_EMAIL = 'deleted-guest@introtravel.com'
def deleted_guest():
    """ used for setting the guest field of a booking when guest is deleted """
    from intro.models import Guest
    from django.conf import settings
    deleted_guest, created = Guest.objects.get_or_create(
        first_name='Deleted',
        last_name='Guest',
        country=settings.COUNTRIES_FIRST[0],
        email=DELETED_GUEST_EMAIL, 
        gender='M')
    return deleted_guest
Run Code Online (Sandbox Code Playgroud)

你不能发送任何参数,你必须小心循环导入。就我而言,我只是设置了一个填充记录,因此父模型有一个预定义的来宾来表示已删除的来宾。有了新的 GDPR 规则,我们必须能够删除访客信息。