#21640: ForeignKey.on_delete doesn't call models save function.
-------------------------------------+-------------------------------------
     Reporter:  traverse.da@…        |                    Owner:  nobody
         Type:  New feature          |                   Status:  closed
    Component:  Database layer       |                  Version:  1.5
  (models, ORM)                      |               Resolution:  wontfix
     Severity:  Normal               |             Triage Stage:
     Keywords:                       |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by russellm):

 * status:  new => closed
 * resolution:   => wontfix
 * type:  Bug => New feature


Comment:

 I disagree that calling save() is inherently the right approach here.

 There are several examples in Django where model functions are not invoked
 when the efficient approach to implementation doesn't route through
 individual models. For example, when you call a bulk delete on a queryset,
 delete() isn't invoked on individual models. This is because the efficient
 implementation of the bulk deletion is to call "DELETE FROM table WHERE
 [condition]", not calling delete on individual models on the query set.
 This is done for efficiency reasons - if you delete a query set of 1000
 items, invoking delete() on 1000 items would be very computationally
 expensive -- even if the delete() method itself was a no-op (because
 function calls aren't free).

 Similarly, a behaviour like on_delete=NULL behaviour can be implemented at
 a database level (i.e., the column definition automatically causes the
 database to set the field to NULL), or it can be implemented with a bulk
 update (UPDATE field=NULL WHERE [delete condition]). Requiring a save on
 every object related to a deleted object would have a similar CPU overhead
 -- if you deleted a query set with 1000 items, you're going to invoke 1000
 save() methods.

 I understand your use case, but IMHO the unintended side effects of your
 proposed feature outweigh the benefits.

 You have a couple of options here as a workaround.

  * You could tackle this at the database level with a stored procedure.

  * You could write a "my_delete()" method (pick a better name, though!)
 that does the thumbnail task generation as a pre-processing step before
 issuing the delete. It's a little ugly,

  * If you're only ever dealing with single object deletion, provide an
 implementation of delete() that does the pre-processing step. This won't
 help you if you run Post.objects.filter(…).delete() (because Post.delete()
 won't be invoked), but if you're only ever deleting individual posts, it
 will work fine.

  * Write your own implementation of SET_NULL. Although it looks like a
 constant, it's actually a function that defines what processing should be
 performed on deleted objects. I haven't looked into this approach in
 detail, but you may find it possible to hook in the pre-delete processing
 as well. See
 [https://github.com/django/django/blob/master/django/db/models/deletion.py
 the source] for details.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/21640#comment:2>
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/079.e709553f1904795c29f48609d8e5252f%40djangoproject.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to