Ticket #5390: m2m_signals.diff

File m2m_signals.diff, 4.4 KB (added by piranha, 7 years ago)

m2m signals patch, updated against signals refactoring

  • django/db/models/fields/related.py

    diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
    a b  
    353353    """Creates a manager that subclasses 'superclass' (which is a Manager)
    354354    and adds behavior for many-to-many related objects."""
    355355    class ManyRelatedManager(superclass):
    356         def __init__(self, model=None, core_filters=None, instance=None, symmetrical=None,
    357                 join_table=None, source_col_name=None, target_col_name=None):
     356        def __init__(self, model=None, core_filters=None, instance=None,
     357                     symmetrical=None, join_table=None, source_col_name=None,
     358                     target_col_name=None, field_name=None):
    358359            super(ManyRelatedManager, self).__init__()
    359360            self.core_filters = core_filters
    360361            self.model = model
     
    365366            self.target_col_name = target_col_name
    366367            self.through = through
    367368            self._pk_val = self.instance._get_pk_val()
     369            self.field_name = field_name
    368370            if self._pk_val is None:
    369371                raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % instance.__class__.__name__)
    370372
     
    434436                existing_ids = set([row[0] for row in cursor.fetchall()])
    435437
    436438                # Add the ones that aren't there already
    437                 for obj_id in (new_ids - existing_ids):
     439                new_ids = new_ids - existing_ids
     440                for obj_id in new_ids:
    438441                    cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
    439442                        (self.join_table, source_col_name, target_col_name),
    440443                        [self._pk_val, obj_id])
     444
     445                added_objs = [obj for obj in objs if (isinstance(obj, self.model) and obj._get_pk_val() in new_ids) or obj in new_ids]
     446                signals.m2m_add_items.send(sender=self.model, instance=self.instance,
     447                                      field_name=self.field_name, objs=added_objs)
     448
    441449                transaction.commit_unless_managed()
    442450
    443451        def _remove_items(self, source_col_name, target_col_name, *objs):
     
    460468                    (self.join_table, source_col_name,
    461469                    target_col_name, ",".join(['%s'] * len(old_ids))),
    462470                    [self._pk_val] + list(old_ids))
     471                signals.m2m_remove_items.send(sender=self.model, instance=self.instance,
     472                                              field_name=self.field_name, objs=objs)
    463473                transaction.commit_unless_managed()
    464474
    465475        def _clear_items(self, source_col_name):
    466476            # source_col_name: the PK colname in join_table for the source object
     477            signals.m2m_clear_items.send(sender=self.model, instance=self.instance,
     478                                         field_name=self.field_name)
    467479            cursor = connection.cursor()
    468480            cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
    469481                (self.join_table, source_col_name),
     
    500512            symmetrical=False,
    501513            join_table=qn(self.related.field.m2m_db_table()),
    502514            source_col_name=qn(self.related.field.m2m_reverse_name()),
    503             target_col_name=qn(self.related.field.m2m_column_name())
     515            target_col_name=qn(self.related.field.m2m_column_name()),
     516            field_name=self.related.field.name
    504517        )
    505518
    506519        return manager
     
    545558            symmetrical=(self.field.rel.symmetrical and instance.__class__ == rel_model),
    546559            join_table=qn(self.field.m2m_db_table()),
    547560            source_col_name=qn(self.field.m2m_column_name()),
    548             target_col_name=qn(self.field.m2m_reverse_name())
     561            target_col_name=qn(self.field.m2m_reverse_name()),
     562            field_name=self.field.name
    549563        )
    550564
    551565        return manager
  • django/db/models/signals.py

    diff --git a/django/db/models/signals.py b/django/db/models/signals.py
    a b  
    1212post_delete = Signal(providing_args=["instance"])
    1313
    1414post_syncdb = Signal(providing_args=["class", "app", "created_models", "verbosity", "interactive"])
     15
     16m2m_add_items = Signal(providing_args=["instance", "field_name", "objs"])
     17m2m_remove_items = Signal(providing_args=["instance", "field_name", "objs"])
     18m2m_clear_items = Signal(providing_args=["instance", "field_name", "objs"])
Back to Top