11

I just need a confirmation for my understanding on Django's implementation of ON DELETE CASCADE from you Django experts.

According to the official Django documentation:

When Django deletes an object, by default it emulates the behavior of the SQL constraint ON DELETE CASCADE -- in other words, any objects which had foreign keys pointing at the object to be deleted will be deleted along with it.

Does the word "emulate" imply that the ON DELETE CASCADE logic is actually implemented in Django instead of at the database level? (I looked into my database and all the tables that contains foreign keys have ON DELETE NO ACTION in their definitions.)

If my understanding is correct, is there any way that I can relocate the ON DELETE CASCADE logic from the app layer to the database layer? I am more looking for a proper way, not an hack, of doing this. (Note: I am using PostgreSQL as my backend.)

tamakisquare
  • 16,659
  • 26
  • 88
  • 129
  • Why? If it works through the Django ORM (with proper maintenance of ORM cache, proper signals being sent to the application, etc.) why would seek to bypass this very complete and sophisticated ORM layer? – S.Lott Jul 15 '11 at 20:21
  • 9
    S.Lott - I am a firm believer that a database should maintain its integrity on its own. It's great to see that ON DELETE CASCADE is handled at the application layer (ex. Django), but this perk is not always available outside of the Django world. What if one day there's some non-Django app accessing and deleting records in my database but it doesn't handle ON DELETE CASCADE but assume the database would do the job. My database would be in big trouble. That's why I am kinda concerned that ON DELETE CASCADE is not been applied at the db level. – tamakisquare Jul 18 '11 at 19:15
  • 1
    "if one day there's some non-Django app accessing and deleting records in my database". Then someone made a terrible mistake. That's like asking "what if an OS process with root privileges delete's a database file?" Or "what if a malicious user runs an application that drops all the database records?" It's trivial to prevent these things. – S.Lott Jul 18 '11 at 19:45
  • 2
    No it's not. It is quite common for multiple applications to use the same database. Your whole assertion is like hiding form fields in Javascript rather than validating the form data server-side :( – DylanYoung Dec 06 '17 at 21:37
  • Not to mention that bulk deletions through the Django ORM can take hours. – DylanYoung Dec 06 '17 at 21:41

2 Answers2

8

If you are asking where the relevant code is implemented: You can find it here.

Implementing the CASCADE-DELETE logic in the application/ORM layer makes sense as this enables the app to get informed when deletion happens (eg. Django's delete signals are fired for the deleted instances), furthermore it is a sane way to enable this feature across different types of databases.

If you are worried about the integrity of your data: Django still sets foreign key constraints if your database supports this (eg. check Postgresql). So your database won't let you delete any rows a foreign key is pointing to.

Try it yourself:

> DELETE FROM accounts_publisher WHERE id=5;
ERROR:  update or delete on table "accounts_publisher" violates foreign key constraint "accounts_publisher_id_411559b18a178e73_fk_accounts_publisher_id" on table "accounts_membership"
DETAIL:  Key (id)=(5) is still referenced from table "accounts_membership".
Bernhard Vallant
  • 49,468
  • 20
  • 120
  • 148
  • 3
    I would add that database level cascading support is being tracked in #21961 (https://code.djangoproject.com/ticket/21961) – Simon Charette Mar 24 '15 at 13:46
  • Thanks @SimonCharette. That's great to know. _"The database can be considerably more efficient, and often can avoid locking situations"_. The ticket describes the exact concern that I have on having the CASCADE-DELETE logic in Django instead of the database itself. I think it's great to make that an option for developers. – tamakisquare Mar 25 '15 at 21:03
  • 2
    Bernhard - This question was asked almost four years ago. My django applications have been running fine, with the CASCADE-DELETE login in the ORM layer, since then, so obviously my concern isn't about data integrity. It's more a question on why paying (with performance and possible locking situations) for duplicating a logic that is already available in the database layer. Like you mentioned, I agree database-agnostic could be a big reason why the core team made that decision. – tamakisquare Mar 25 '15 at 21:10
  • 3
    @tamakisquare and the other reason is that your application can react to instances being deleted (eg. using the `pre_delete`/`post_delete`) signals... – Bernhard Vallant Mar 26 '15 at 12:08
-1

FYI, this has been configurable since django 1.3: https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ForeignKey.on_delete

Basically you need to set on_delete to DO_NOTHING and add the cascade logic to the DB yourself:

DO_NOTHING: Take no action. If your database backend enforces referential integrity, this will cause an IntegrityError unless you manually add a SQL ON DELETE constraint to the database field (perhaps using initial sql).

related
  • 794
  • 5
  • 14
  • AFAIK this behaviour is only being _emulated_ by Django. Why does Django not set the behaviour directly in the FK at database level, like the original question asks? – dukebody Mar 21 '15 at 10:28