views:

611

answers:

2

I'd like to delete an instance of a model, but only if it doesn't have any other instance of another class with a foreign key pointing to it. From Django documentation:

When Django deletes an object, it emulates the behavior of the SQL constraint ON DELETE CASCADE -- in other words, any objects which had foreign keys pointing at the object to be deleted will be deleted along with it.

In a given example:

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
# ........

I'd like something like:

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"

Should print the error. I know I can check for specific instances the foreignkey sets, like in this case check t.TestB_set(), but I am looking for a more general solution for any given model.

A: 

Check the related objects length

t=TestA.objects.get(name="textA1")
if not t.testB_set.all().count():#related members
  t.delete()
czarchaic
That works well for a specific case, but I wanted a more general solution so I don't have to write a different delete test for every model and update it if another object references to it.
plmet
+2  A: 

I finally solved it using this http://stackoverflow.com/questions/681497/nullable-foreignkeys-and-deleting-a-referenced-model-instance, the solution looks like:

    # 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
plmet