Login

Clear nullable foreign keys on delete

Author:
psagers
Posted:
December 2, 2008
Language:
Python
Version:
1.0
Tags:
model delete cascade
Score:
0 (after 0 ratings)

Django 1.0 is apparently hard-coded for cascading deletes. I find that I often have nullable foreign keys on models whose records must not be deleted along with those they refer to. I override Model.delete() in an intermediate base class and execute this method to clear out all nullable foreign keys before allowing a delete to proceed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from django.db import models

class Model(models.Model):
    """
    Intermediate model base class.
    """
    class Meta:
        abstract = True

    def delete(self, *args, **kwargs):
        self.clear_nullable_related()
        super(Model, self).delete(*args, **kwargs)

    def clear_nullable_related(self):
        """
        Recursively clears any nullable foreign key fields on related objects.
        Django is hard-wired for cascading deletes, which is very dangerous for
        us. This simulates ON DELETE SET NULL behavior manually.
        """
        for related in self._meta.get_all_related_objects():
            accessor = related.get_accessor_name()
            related_set = getattr(self, accessor)

            if related.field.null:
                related_set.clear()
            else:
                for related_object in related_set.all():
                    related_object.clear_nullable_related()

More like this

  1. update primary key (and cascade to child tables) by guettli 3 years, 1 month ago
  2. PostgreSQL ON DELETE CASCADE by mjt 5 years, 5 months ago
  3. update primary key (cascade to child tables and inherited models) by variant 1 year, 11 months ago
  4. Binding signals to abstract models by andreterra 2 years, 11 months ago
  5. Improved generic foreign key manager 2 by Nomalz 5 years, 5 months ago

Comments

peterbe (on June 8, 2010):

@jdunck this is still a problem. Even in Django 1.2.1

#

skyjur (on July 28, 2010):

I've modified clear_nullable_related() because I was getting exceptions in some cases. Here is my modified code:

from django.core.exceptions import ObjectDoesNotExist

def clear_nullable_related(self):
    """
    Recursively clears any nullable foreign key fields on related      objects.
    Django is hard-wired for cascading deletes, which is very dangerous for
    us. This simulates ON DELETE SET NULL behavior manually.
    """
    for related in self._meta.get_all_related_objects():
        accessor = related.get_accessor_name()
        try:
            related_set = getattr(self, accessor)
        except ObjectDoesNotExist:
            continue

        if related.field.null:
            related_set.clear()
        elif related.field.rel.multiple:
            for related_object in related_set.all():
                related_object.clear_nullable_related()

#

guettli (on March 14, 2012):

Django 1.3 has support for "ON DELETE": ForeignKey.on_delete

#

Please login first before commenting.