我有一个IPv4Manage模型,其中有一个vlanedipv4network
字段:
class IPv4Manage(models.Model):
...
vlanedipv4network = models.ForeignKey(
to=VlanedIPv4Network, related_name="ipv4s", on_delete=models.xxx, null=True)
我们知道,在on_delete
param上,我们会填写models.xxx
,例如models.CASCADE
。
是否可以定制一个功能,填充那里?我想在那里做其他逻辑事情。
答案 0 :(得分:1)
CASCADE和PROTECT等实际上是函数,因此您应该能够在那里注入自己的逻辑。但是,需要对代码进行一定程度的检查才能确定如何获得您正在寻找的效果。
根据您的想法,它可能相对容易,例如PROTECT功能只会引发异常:
def PROTECT(collector, field, sub_objs, using):
raise ProtectedError(
"Cannot delete some instances of model '%s' because they are "
"referenced through a protected foreign key: '%s.%s'" % (
field.remote_field.model.__name__, sub_objs[0].__class__.__name__, field.name
),
sub_objs
)
但是如果你想要更复杂的东西,你必须要了解collector
正在做什么,这当然是可以发现的。
答案 1 :(得分:1)
可以在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)
而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)
所以,如果你弄清楚那些参数是什么,那么你应该能够定义自己的函数来传递给模型字段的on_delete
参数。 collector
很可能是Collector
的一个实例(在同一个文件中定义,不确定它到底是什么),field
很可能是要删除的模型字段,{ {1}}可能是该字段与对象相关的实例,sub_objs
表示正在使用的数据库。
还有替代自定义逻辑用于删除,如果覆盖on_delete对你来说可能有点矫枉过正。
post_delete和pre_delete允许您定义一些自定义逻辑,以便在删除实例之前或之后运行。
using
最后you can override the delete()
method of the Model/Queryset但请注意使用此方法批量删除的注意事项:
批量操作不会调用重写的模型方法
请注意,在使用QuerySet批量删除对象或作为级联删除的结果时,不一定要调用对象的delete()方法。为确保执行自定义删除逻辑,您可以使用pre_delete和/或post_delete信号。
答案 2 :(得分:1)
另一个有用的解决方案是使用models.SET()
您可以传递函数的地方(下例中的deleted_guest)
guest = models.ForeignKey('Guest',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
您无法发送任何参数,您必须小心循环导入。在我的情况下,我只是设置一个填充记录,因此父模型有一个预定义的来宾代表一个已被删除的来宾。使用新的GDPR规则,我们必须能够删除访客信息。
答案 3 :(得分:0)
没有什么可以阻止你添加你自己的逻辑。但是,您需要考虑多种因素,包括与您正在使用的数据库的兼容性。
对于大多数用例,如果数据库设计正确,开箱即用的逻辑就足够了。请在此处查看您的可用选项https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.ForeignKey.on_delete。