On Friday, September 27, 2013 1:29:29 AM UTC+3, Xof wrote: > > > On Sep 26, 2013, at 3:28 PM, Christophe Pettus > <x...@thebuild.com<javascript:>> > wrote: > > Perhaps a CASCADE_DB and SET_NULL_DB options on on_delete? > > And, to be clear, I *am* volunteering to take a go at this code, not just > whine. :) >
Some things to consider: 1. What to do if given DB doesn't support cascades in DB (sqlite at least, no idea of MySQL)? Initial feeling is that Django should do the cascades in Python code in these cases. 2. What to do if you have delete signals + db cascades set for given model? Options are to do nothing at all, give a warning (manage.py check might be able to do so) or raise an error in model validation. 3. A model definition like A -- db cascade -> B -- cascade in python -> C is another problematic case. a_obj.delete() will cascade to B, but then that deletion will fail because of C constraint not cascading. Again possibilities are do nothing/warn/error 4. A slight variation of above - generic foreign key cascades - here it will be impossible to handle the cascades in DB (unless we want to write custom triggers for this). And, the inconsistent state left behind will not be spotted by the DB either as there aren't any constraints in the DB for generic foreign keys. So, this is slightly worse than #3. 5. Parent cascades: If you have model Child(Parent), then there will be foreign key from child to parent, but not from parent to child. This means that DB can't cascade child model deletion to the parent model. So, there is again possibility for inconsistent state. So, if you have Child -- db cascade -> SomeModel, and you delete somemodel instance then what to do to get the Child's parent table data deleted? Numbers #4 and #5 seem hardest. Especially the parent cascade case seems hard, for generic foreign keys just documenting "don't do that" seems good enough. For reference, the problematic data model is this: class Parent(Model): id = AutoField() class SomeModel(Model): pass class Child(Parent): parent_ptr = models.OneToOneField(Parent, on_delete=DB_CASCADE, parent_link=True) somemodel = models.ForeignKey(SomeModel, on_delete=DB_CASCADE) It generates schema like this: create table parent( id serial primary key ); create table child( parent_ptr_id integer primary key references parent(id) on delete cascade, somemodel_id integer not null references somemodel(id) on delete cascade ); create table somemodel( id serial primary key ); Now, parent data deletion will correctly cascade to child in the DB, but child data deletion will not cascade to parent. Django's interpretation is that when you delete a child instance, you delete also all parent data at the same time. When somemodel delete cascades to child in the DB then associated parent data will not be deleted. Adding nullable foreign key from parent to child might work, that is add a SymmetricOneToOneField into Django. Data model would be: create table parent( id serial primary key, child_id integer references child(parent_ptr_id) on delete cascade -- this of course also needs deferrable initially deferred qualifier to work... ); create table child( parent_ptr_id integer primary key references parent(id) on delete cascade, ... ); - Anssi -- You received this message because you are subscribed to the Google Groups "Django developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To post to this group, send email to django-developers@googlegroups.com. Visit this group at http://groups.google.com/group/django-developers. For more options, visit https://groups.google.com/groups/opt_out.