#34733: m2m_changed signal is unaware if .set() method is being called
-------------------------------------+-------------------------------------
               Reporter:  lekjos     |          Owner:  nobody
                   Type:  New        |         Status:  new
  feature                            |
              Component:  Database   |        Version:  dev
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 When a `related_m2m_field.set()` method is called, the `m2m_changed`
 signal is fired four times for action: `pre_remove`, `post_remove`,
 `pre_add`, and `post_add` (or `pre_clear` / `post_clear`).

 This poses a problem if the signal is supposed to run validation on the
 final state of the model. For example, let's say I have a model called
 `Customer` with a many-to-many relation to `SubscriptionPlan` and I have a
 `m2m_changed` signal that is supposed to validate if their
 SubscriptionPlan is valid.

 If I call `subscription_plans.set([some_plans])`, the many-to-many manager
 will first call `subscription_plans.remove()` then `.add()` inside an
 atomic transaction. If my signal validates on the first `remove()`, it
 could be in an invalid state, even though it won't be by the time the
 `.add()` completes.

 To get around this, I had to create a custom ManyToManyField with a custom
 RelatedManager that set an instance variable on the model when the
 `.set()` method was called. I'd like to propose adding a feature to the
 RelatedManager or to the signals to make the `m2m_changed` signal aware of
 if the `.set()` method was called when running. This could be a private
 attribute on the instance or extra information passed to the signal
 receiver.

 If this feature already exists or there's a decent workaround, let me know
 and i'll close the ticket! Otherwise, I have a patch in mind that I can
 raise a PR for and attach.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34733>
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 view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701897aa4eb79-e64e93d0-2dde-418d-94ee-6d45e4c9b0e7-000000%40eu-central-1.amazonses.com.

Reply via email to