Opened 13 years ago

Closed 13 years ago

Last modified 13 years ago

#16648 closed Bug (invalid)

Router unable to delete relationships spanning multiple DBs

Reported by: chadlyon Owned by: nobody
Component: Database layer (models, ORM) Version: 1.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


The following method in django.db.models.Model has a deficiency such that if you define a router that uses _meta info to determine where to write and your model objects have Fkey dependencies spanning the multiple DBs then you get an integrity error because this method assumes a single DB when collecting dependent objects to delete:

def delete(self, using=None):
        using = using or router.db_for_write(self.__class__, instance=self)
        assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name,

        # Find all the objects than need to be deleted.
        seen_objs = CollectedObjects()

        # Actually delete the objects.
        delete_objects(seen_objs, using)

Basically, router.db_for_write(…) should be called inside delete_objects(…) for each seen_objs

You can work around this by overriding delete(...) for your models but I think this should be fixed in base.

Change History (2)

comment:1 by Ramiro Morales, 13 years ago

Resolution: invalid
Status: newclosed

Django doesn't support cross-database FKr elationships.

Closing for the same reson and using the same values as #16240.

comment:2 by Chad Lyon <chad.lyon@…>, 13 years ago

Now wait a second, there is still a problem with this method in that it calls delete_objects(...) which descends into all children and deletes them by constructing SQL (FWIU) to perform the delete. This circumvents the delete(self, using=None) routine on the Child objects. Meaning if I have overridden delete() then my overridden routine doesn't get called for my Children only for the Parent. This seems to be inconsistent behavior. Don't you think delete() should be called on all seen_objs?

Note: See TracTickets for help on using tickets.
Back to Top