mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[1.10.x] Fixed #26686 -- Fixed crash when registering model signals with abstract senders.
Backport of 08014fe75b from master
			
			
This commit is contained in:
		| @@ -3,6 +3,7 @@ from functools import partial | ||||
|  | ||||
| from django.db.models.utils import make_model_tuple | ||||
| from django.dispatch import Signal | ||||
| from django.utils import six | ||||
| from django.utils.deprecation import RemovedInDjango20Warning | ||||
|  | ||||
|  | ||||
| @@ -15,15 +16,15 @@ class ModelSignal(Signal): | ||||
|     of the `app_label.ModelName` form. | ||||
|     """ | ||||
|     def _lazy_method(self, method, apps, receiver, sender, **kwargs): | ||||
|         from django.db.models.options import Options | ||||
|  | ||||
|         # This partial takes a single optional argument named "sender". | ||||
|         partial_method = partial(method, receiver, **kwargs) | ||||
|         # import models here to avoid a circular import | ||||
|         from django.db import models | ||||
|         if isinstance(sender, models.Model) or sender is None: | ||||
|             # Skip lazy_model_operation to get a return value for disconnect() | ||||
|         if isinstance(sender, six.string_types): | ||||
|             apps = apps or Options.default_apps | ||||
|             apps.lazy_model_operation(partial_method, make_model_tuple(sender)) | ||||
|         else: | ||||
|             return partial_method(sender) | ||||
|         apps = apps or models.base.Options.default_apps | ||||
|         apps.lazy_model_operation(partial_method, make_model_tuple(sender)) | ||||
|  | ||||
|     def connect(self, receiver, sender=None, weak=True, dispatch_uid=None, apps=None): | ||||
|         self._lazy_method(super(ModelSignal, self).connect, apps, receiver, sender, dispatch_uid=dispatch_uid) | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| from __future__ import unicode_literals | ||||
|  | ||||
| from django.apps.registry import Apps | ||||
| from django.db import models | ||||
| from django.db.models import signals | ||||
| from django.dispatch import receiver | ||||
| @@ -317,3 +318,14 @@ class LazyModelRefTest(BaseSignalTest): | ||||
|  | ||||
|         Created() | ||||
|         self.assertEqual(received, []) | ||||
|  | ||||
|     def test_register_model_class_senders_immediately(self): | ||||
|         """ | ||||
|         Model signals registered with model classes as senders don't use the | ||||
|         Apps.lazy_model_operation() mechanism. | ||||
|         """ | ||||
|         # Book isn't registered with apps2, so it will linger in | ||||
|         # apps2._pending_operations if ModelSignal does the wrong thing. | ||||
|         apps2 = Apps() | ||||
|         signals.post_init.connect(self.receiver, sender=Book, apps=apps2) | ||||
|         self.assertEqual(list(apps2._pending_operations), []) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user