Opened 4 years ago

Closed 4 years ago

Last modified 4 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 Changed 4 years ago by ramiro

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

Django doesn't support cross-database FKr elationships.

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

comment:2 Changed 4 years ago by Chad Lyon <chad.lyon@…>

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