Python 如何查找对实例的所有Django外键引用
如何找到对特定Django模型实例的所有直接外键引用 我想删除一条记录,但我想维护引用它的所有子记录,因此我试图在删除之前用另一条记录“交换”对旧记录的引用 类似的问题涉及收集器类。我试过:Python 如何查找对实例的所有Django外键引用,python,django,Python,Django,如何找到对特定Django模型实例的所有直接外键引用 我想删除一条记录,但我想维护引用它的所有子记录,因此我试图在删除之前用另一条记录“交换”对旧记录的引用 类似的问题涉及收集器类。我试过: obj_to_delete = MyModel.objects.get(id=blah) new_obj = MyModel.objects.get(id=blah2) collector = Collector(using='default') collector.collect([obj_to_dele
obj_to_delete = MyModel.objects.get(id=blah)
new_obj = MyModel.objects.get(id=blah2)
collector = Collector(using='default')
collector.collect([obj_to_delete])
for other_model, other_data in collector.field_updates.iteritems():
for (other_field, _value), other_instances in other_data.iteritems():
# Why is this necessary?
if other_field.rel.to is not type(first_obj):
continue
for other_instance in other_instances:
setattr(other_instance, other_field.name, new_obj)
other_instance.save()
# All FK references should be gone, so this should be safe to delete.
obj_to_delete.delete()
然而,这似乎有两个问题:
collector.field\u updates
包含对模型和字段的引用,这些引用与我的目标obj\u to\u delete
无关李>
obj_to_delete.delete()
调用失败,IntegrityErrors抱怨仍然引用它的剩余记录,这些记录没有被收集器捕获我只需要一种方法来查找单个模型实例的所有FK引用。我不需要任何像Django的标准删除视图中使用的那种奇特的依赖项查找。您可以使用Django的反向外键支持 假设您有两个模型,如下所示:
class Foo(models.Model):
name = models.CharField(max_length=10)
class Bar(models.Model):
descr = models.CharField(max_length=100)
foo = models.ForeignKey(Foo)
然后您就知道您可以执行
bar\u instance.foo
来访问它所键控的foo对象。但是,您可以在Foo
实例上使用反向外键来获取指向它的所有Bar
对象,例如,使用Foo.Bar\u集
就个人而言,我认为最好的选择是避免级联删除
使用适当的Django选项在相关模型中声明外键,例如
on_delete=models.SET_NULL
应该足够了
借用@Joseph回答中的示例模型:
class Foo(models.Model):
name = models.CharField(max_length=10)
class Bar(models.Model):
descr = models.CharField(max_length=100)
foo = models.ForeignKey(Foo, blank=True, null=True, on_delete=models.SET_NULL))
如官方文件所述,以下是您可以使用和试验的预定义行为:
- SET_NULL:将外键设置为NULL;这仅在null为空时才可能 对
- SET_DEFAULT:将ForeignKey设置为默认值;违约 必须设置外键
- SET():将ForeignKey设置为传递给SET()的值,或者如果 传入callable,即调用它的结果。在大多数情况下,为了避免在导入models.py时执行查询,需要传递callable:
- 什么都不做:不要采取行动。如果您的数据库后端强制 引用完整性,这将导致IntegrityError,除非 在数据库字段中手动添加SQL ON DELETE约束
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class MyModel(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user))