Ticket #6778: patch.diff
File patch.diff, 7.4 KB (added by , 16 years ago) |
---|
-
django/django/db/models/fields/related.py
424 424 return obj, created 425 425 get_or_create.alters_data = True 426 426 427 def _add_items_signal(func): 428 def _add_items(self, source_col_name, target_col_name, *objs): 429 func(self, source_col_name, target_col_name, *objs) 430 if objs: 431 self._object_added_signal(objs) 432 return _add_items 433 434 def _remove_items_signal(func): 435 def _remove_items(self, source_col_name, target_col_name, *objs): 436 func(self, source_col_name, target_col_name, *objs) 437 if objs: 438 self._object_removed_signal(objs) 439 return _remove_items 440 441 def _clear_items_signal(func): 442 def _clear_items(self, source_col_name): 443 # check if there are any registered receivers 444 # if none, don't waste time performing query 445 will_signal = self._test_signal_has_receivers(signals.m2m_related_data_removed) 446 if will_signal: 447 removed = list(self.all()) 448 func(self,source_col_name) 449 # check again, why fire off signal if no one is listening? 450 if will_signal: 451 self._object_removed_signal(removed) 452 return _clear_items 453 427 454 def _add_items(self, source_col_name, target_col_name, *objs): 428 455 # join_table: name of the m2m link table 429 456 # source_col_name: the PK colname in join_table for the source object … … 455 482 [self._pk_val, obj_id]) 456 483 transaction.commit_unless_managed() 457 484 485 # add fire off signal when items are added 486 _add_items = _add_items_signal(_add_items) 487 458 488 def _remove_items(self, source_col_name, target_col_name, *objs): 459 489 # source_col_name: the PK colname in join_table for the source object 460 490 # target_col_name: the PK colname in join_table for the target object … … 477 507 [self._pk_val] + list(old_ids)) 478 508 transaction.commit_unless_managed() 479 509 510 _remove_items = _remove_items_signal(_remove_items) 511 480 512 def _clear_items(self, source_col_name): 481 513 # source_col_name: the PK colname in join_table for the source object 482 514 cursor = connection.cursor() … … 484 516 (self.join_table, source_col_name), 485 517 [self._pk_val]) 486 518 transaction.commit_unless_managed() 519 520 _clear_items = _clear_items_signal(_clear_items) 487 521 522 def _object_removed_signal(self, objs): 523 signals.m2m_related_data_removed.send(sender=self.instance, objs_removed=objs, join_table=self.join_table ) 524 525 def _object_added_signal(self,objs): 526 signals.m2m_related_data_added.send(sender=self.instance, objs_added=objs , join_table = self.join_table) 527 528 def _test_signal_has_receivers(self, signal): 529 return len(signal.receivers) > 0 530 488 531 return ManyRelatedManager 489 532 490 533 class ManyRelatedObjectsDescriptor(object): -
django/django/db/models/signals.py
12 12 post_delete = Signal(providing_args=["instance"]) 13 13 14 14 post_syncdb = Signal(providing_args=["class", "app", "created_models", "verbosity", "interactive"]) 15 16 m2m_related_data_added = Signal(providing_args=['objs_added','join_table']) 17 m2m_related_data_removed = Signal(providing_args=['objs_removed','join_table']) 18 No newline at end of file -
django/tests/modeltests/m2m_signals/models.py
1 """ 2 Testing signals fired when item(s) are added to a many-to-many relation, 3 when items are removed and when the relation is cleared 4 """ 5 print('testing m2m signals') 6 7 from django.db import models 8 from django.db.models import signals 9 10 class Pizza(models.Model): 11 name = models.CharField(max_length=60) 12 13 class Topping(models.Model): 14 name = models.CharField(max_length=50) 15 pizzas = models.ManyToManyField(Pizza) 16 17 def relation_made(signal, sender, **named): 18 names = str([str(x.name) for x in named['objs_added']]) 19 print '%s just associated with %s' % (sender.name, names) 20 21 def relation_unmade(signal, sender, **named): 22 names = str([str(x.name) for x in named['objs_removed']]) 23 print '%s just disassociated with %s' % (sender.name, names) 24 25 signals.m2m_related_data_added.connect(relation_made) 26 signals.m2m_related_data_removed.connect(relation_unmade) 27 28 __test__ = {'API_TESTS':""" 29 >>> p1, p2, p3 = Pizza(name='veggie'), Pizza(name='cheese'), Pizza(name='pepperoni') 30 >>> p1.save() 31 >>> p2.save() 32 >>> p3.save() 33 >>> t1, t2, t3, t4= Topping(name='cheese'), Topping(name='red pepper'), \ 34 Topping(name='mushrooms'), Topping(name='pepperoni') 35 >>> t1.save() 36 >>> t2.save() 37 >>> t3.save() 38 >>> t4.save() 39 40 # associate some data 41 >>> p1.topping_set.add(t1,t2,t3) 42 veggie just associated with ['cheese', 'red pepper', 'mushrooms'] 43 >>> p2.topping_set.add(t1) 44 cheese just associated with ['cheese'] 45 >>> p3.topping_set.add(t1,t3,t4) 46 pepperoni just associated with ['cheese', 'mushrooms', 'pepperoni'] 47 >>> p3.topping_set.remove(t3) 48 pepperoni just disassociated with ['mushrooms'] 49 >>> p3.topping_set.clear() 50 pepperoni just disassociated with ['cheese', 'pepperoni'] 51 >>> t1.pizzas.add(p3) 52 cheese just associated with ['pepperoni'] 53 >>> t1.pizzas.clear() 54 cheese just disassociated with ['veggie', 'cheese', 'pepperoni'] 55 """} -
django/docs/ref/signals.txt
162 162 163 163 Note that the object will no longer be in the database, so be very 164 164 careful what you do with this instance. 165 166 m2m_related_data_added 167 ----------- 165 168 169 .. data:: django.db.models.signals.m2m_related_data_added 170 :module: 171 172 Like :data:`m2m_related_data_removed`, but sent when data is added. 173 174 Arguments sent with this signal: 175 176 ``sender`` 177 The instance which just had data asscoiated with it. 178 179 ``objs_added`` 180 The object(s) which were just associated with the sender. 181 182 ``join_table`` 183 The join table between the relevant many-to-many relationship. 184 185 m2m_related_data_removed 186 ----------- 187 188 .. data:: django.db.models.signals.m2m_related_data_added 189 :module: 190 191 Like :data:`m2m_related_data_added`, but sent when data is removed. 192 193 Arguments sent with this signal: 194 195 ``sender`` 196 The instance which just had data asscoiated with it. 197 198 ``objs_removed`` 199 The object(s) which were just disassociated with the sender. 200 201 ``join_table`` 202 The join table between the relevant many-to-many relationship. 203 166 204 class_prepared 167 205 -------------- 168 206