#21961: Add support for database-level cascading options
-------------------------------------+-------------------------------------
Reporter: Christophe Pettus | Owner: Nick
| Stefan
Type: New feature | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Nick Stefan):
Hi Dylan.
I think your thoughts do make logical sense in response to Carl. However,
that proposal was written a long time ago (it was circa 2014). I think
most of that "ambiguity" discussed then comes from 2014 DBs not
supporting ON DELETE CASCADE. That lack of support then required the need
to have automatic fall backs.
In 2017, all of the supported databases should support ON DELETE CASCADE,
so a single on_delete kwarg still makes sense to me.
I guess there is "ambiguity" regarding signals etc, but I don't think that
should be the case. DO_NOTHING has been a value for a long time.
DB_CASCADE is really just DO_NOTHING plus some more SQL, so it should be
understood that there can't be signals.
Of course, that's just my opinion, and I admit that it might be unpopular
based on how my PR has fared lol :).
I opened a PR back in the summer proving the concept, and added pre check
tests to prevent hairy situations like generic foreign keys, concrete
model inheritance, etc: https://github.com/django/django/pull/8661 .
--Nick
Replying to [comment:16 Dylan Young]:
> A separate kwarg (`on_delete_db`) is a much better proposal:
>
> 1) It (together with adequate documentation) eliminates *ALL* of the
ambiguities present in the current proposal.
> 2) When this kwarg is unspecified, it should default to the value of
`on_delete`, ensuring as closely as possible consistency between raw
database operations and Django operations.
> 3) Otherwise it leaves granular control up to the user: Don't need
delete signals (postgres should be able to support post_delete, no?)? Use
the configuration outlined by Carl. Need delete signals in your Django
application, but still want sane deletion behaviour in other applications
using your DB? Simply set `on_delete`. Need your other applications to
have different deletion behaviour? Just reverse the configuration outlined
by Carl... Or any number of options?
> 4) You could add some special flags that isolate the ORM-level deletion
to specific DB-problematic cases (Generic Foreign Keys, Inheritance...),
thus eliminating the overhead of python-space constraints in the majority
of cases.
> 5) Maybe it also makes testing Django's ORM on_delete behaviour easier?
By adding the ability to easily cross-reference with the Database's
internal implementation... could be wrong on that, but with `on_delete`
set to cascade, you would expect the final deletion call of the original
object (after all the ORM work to delete related objects) to only delete a
single instance right? If it deletes more than expected, the error in the
ORMs deletion emulation is exposed.
>
> An extra thought on Postgres:
>
> It seems like it should be possible to support signals with DB-level
constraints. Actually any DB that supports `returning` + transactions
should be capable, no?
>
>
> Replying to [comment:9 Carl Meyer]:
> > I think we should consider introducing this feature as a totally
separate kwarg (`on_delete_db`) rather than conflating it with the
existing Python-level `on_delete`. The various edge cases and implicit
fallbacks in the existing proposal worry me, and I think it would be
better to be more explicit and clear about what is happening on the
database level vs the Python level.
> >
> > Right now the contract of `on_delete` is very simple: it takes a
Python callable which will be called when a delete cascades. There is
nothing at all special about the built-in callables, they are just
conveniences for common cases. The current API proposal complicates that
contract dramatically: now you have an `on_delete` kwarg which sometimes
accepts Python callables but can also accept magical constants which do
something entirely different (and also have an implicit fallback
relationship with one of the built-in callables).
> >
> > So under my proposal, if you want database-level cascade, you would
specify `on_delete=models.DO_NOTHING, on_delete_db=models.DB_CASCADE` or
similar. Sure this is a bit more verbose, but I think that's worth it for
the gains in clarity and simplicity.
> >
> > For similar reasons, I feel pretty strongly that we should NOT
automatically fallback from db-cascade to non-db-cascade depending on the
backend capabilities. It introduces too many differences in behavior
depending on db backend. Trying to claim to provide cross-db portability
when we can't really do so consistently is worse than simply not claiming
to provide it at all. DB-level cascade (like many other "advanced" db-
level features) is something you should only take advantage of when you
know your code will be running on a database that supports it, full stop.
Use of `on_delete_db` on a backend that can't support it should be an
error.
--
Ticket URL: <https://code.djangoproject.com/ticket/21961#comment:17>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/061.4b8b7999afe3f05ee5690c286e00fab4%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.