Opened 6 years ago
Closed 6 years ago
#29615 closed Cleanup/optimization (duplicate)
Document difference in behaviour between m2m_changed behaviour for add() vs remove() when called multiple times.
Reported by: | nirmalraghavan | Owned by: | Sanyam Khurana |
---|---|---|---|
Component: | Documentation | Version: | 2.0 |
Severity: | Normal | Keywords: | signals, m2m_changed |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
Consider the following Model,
class MyModel(models.Model): likes = models.ForeignKey(User)
Now if I add a user to the likes field as below,
myObj.likes.add(user)
my m2m_changed receiver method will be called in signals module with action post_add. And if I try to add the same user again. nothing will happen which is fine.
And when I try to remove the user as below,
myObj.likes.remove(user)
m2m_changed receiver method is called with action post_remove. And if I try to remove the same user again, this time also m2m_changed receiver method is called. Even if there's no such user exist in ManyToMany field, django will emit post_remove signal.
Change History (6)
comment:1 by , 6 years ago
comment:2 by , 6 years ago
Component: | Database layer (models, ORM) → Documentation |
---|---|
Keywords: | signals m2m_changed added |
Triage Stage: | Unreviewed → Accepted |
Type: | Uncategorized → Cleanup/optimization |
OK, this is distinct from #22296.
There is an anomaly here. `add()` calls filter out the existing instances before processing the ids:
vals = (self.through._default_manager.using(db) .values_list(target_field_name, flat=True) .filter(**{ source_field_name: self.related_val[0], '%s__in' % target_field_name: new_ids, })) new_ids.difference_update(vals)
This is necessary to avoid django.db.utils.IntegrityError: UNIQUE constraint failed ...
errors.
No such problem exists with duplicate delete()
calls, so no such filtering is done.
I'm guessing that the extra DB query would not be considered worth it to avoid the extra signal call here. (Anyone?)
But I think this probably could be documented as a note at the end of the `m2m_changed` reference.
comment:3 by , 6 years ago
Summary: | post_remove action is called even though there's no relation → Document difference in behaviour between m2m_changed behaviour for add() vs remove() when called multiple times. |
---|
comment:4 by , 6 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:5 by , 6 years ago
Patch needs improvement: | set |
---|
comment:6 by , 6 years ago
Resolution: | → duplicate |
---|---|
Status: | assigned → closed |
As far as I can tell, the report that the m2m_changed
signal isn't sent for redundant add()
calls isn't correct. The signal is still sent on any subsequent add()
, but pk_set
is empty. This looks like a duplicate of #27462.
Is this a duplicate of #22296?