2009-12-16 52 views
3

我想删除模型的一个实例,但前提是它没有任何其他类的实例,并且外键指向它。从Django文档:Django模型ON DELETE CASCADE策略,模拟ON DELETE RESTRICT而不是一般解决方案

当Django删除一个对象时,它模拟SQL约束的行为ON DELETE CASCADE - 换句话说,任何有外键指向要删除的对象的对象将被删除用它。

在一个给定的例子:

class TestA(models.Model) 
    name = models.CharField() 

class TestB(models.Model) 
    name = models.CharField() 
    TestAs = models.ManyToManyField(TestA) 

# More classes with a ManyToMany relationship with TestA 
# ........ 

我想是这样的:

tA = TestA(name="testA1") 
tB = TestB(name="testB1") 
tB.testAs.add(tA) 

t = TestA.objects.get(name="testA1") 

if is_not_foreignkey(t): 
    t.delete() 
else: 
    print "Error, some instance is using this" 

应该打印错误。我知道我可以检查外键设置的具体实例,比如在这种情况下检查t.TestB_set(),但是我正在寻找任何给定模型的更一般的解决方案。

回答

0

检查相关的对象长度

t=TestA.objects.get(name="textA1") 
if not t.testB_set.all().count():#related members 
    t.delete() 
+0

这对于一个特定的情况很好,但我想要一个更通用的解决方案,所以我不想不必为每个模型编写不同的删除测试,并在其他对象引用它时更新它。 – plmet 2009-12-18 08:34:39

2

我终于用这个Nullable ForeignKeys and deleting a referenced model instance解决它,解决办法是这样的:

# Check foreign key references 
    instances_to_be_deleted = CollectedObjects() 
    object._collect_sub_objects(instances_to_be_deleted) 

    # Count objects to delete 
    count_instances_to_delete = 0 
    for k in instances_to_be_deleted.unordered_keys(): 
     count_instances_to_delete += len(instances_to_be_deleted[k]) 

    if count_instances_to_delete == 1: 
     object.delete() 
    else: 
     pass 
0

CollectedObjects()在Django 1.3辗转 - 这里有一个电流法:

from compiler.ast import flatten 
from django.db import DEFAULT_DB_ALIAS 
from django.contrib.admin.util import NestedObjects 

def delete_obj_if_no_references(obj): 
    collector = NestedObjects(using=DEFAULT_DB_ALIAS) 
    collector.collect([obj]) 
    objs = flatten(collector.nested()) 
    if len(objs) == 1 and objs[0] is obj: 
     obj.delete() 
     return True 
    return False