You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

70 lines
2.7 KiB

  1. from django.apps import apps
  2. from django.dispatch import Signal
  3. from django.utils import six
  4. class_prepared = Signal(providing_args=["class"])
  5. class ModelSignal(Signal):
  6. """
  7. Signal subclass that allows the sender to be lazily specified as a string
  8. of the `app_label.ModelName` form.
  9. """
  10. def __init__(self, *args, **kwargs):
  11. super(ModelSignal, self).__init__(*args, **kwargs)
  12. self.unresolved_references = {}
  13. class_prepared.connect(self._resolve_references)
  14. def _resolve_references(self, sender, **kwargs):
  15. opts = sender._meta
  16. reference = (opts.app_label, opts.object_name)
  17. try:
  18. receivers = self.unresolved_references.pop(reference)
  19. except KeyError:
  20. pass
  21. else:
  22. for receiver, weak, dispatch_uid in receivers:
  23. super(ModelSignal, self).connect(
  24. receiver, sender=sender, weak=weak, dispatch_uid=dispatch_uid
  25. )
  26. def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):
  27. if isinstance(sender, six.string_types):
  28. try:
  29. app_label, model_name = sender.split('.')
  30. except ValueError:
  31. raise ValueError(
  32. "Specified sender must either be a model or a "
  33. "model name of the 'app_label.ModelName' form."
  34. )
  35. try:
  36. sender = apps.get_registered_model(app_label, model_name)
  37. except LookupError:
  38. ref = (app_label, model_name)
  39. refs = self.unresolved_references.setdefault(ref, [])
  40. refs.append((receiver, weak, dispatch_uid))
  41. return
  42. super(ModelSignal, self).connect(
  43. receiver, sender=sender, weak=weak, dispatch_uid=dispatch_uid
  44. )
  45. pre_init = ModelSignal(providing_args=["instance", "args", "kwargs"], use_caching=True)
  46. post_init = ModelSignal(providing_args=["instance"], use_caching=True)
  47. pre_save = ModelSignal(providing_args=["instance", "raw", "using", "update_fields"],
  48. use_caching=True)
  49. post_save = ModelSignal(providing_args=["instance", "raw", "created", "using", "update_fields"], use_caching=True)
  50. pre_delete = ModelSignal(providing_args=["instance", "using"], use_caching=True)
  51. post_delete = ModelSignal(providing_args=["instance", "using"], use_caching=True)
  52. m2m_changed = ModelSignal(
  53. providing_args=["action", "instance", "reverse", "model", "pk_set", "using"],
  54. use_caching=True,
  55. )
  56. pre_migrate = Signal(providing_args=["app_config", "verbosity", "interactive", "using"])
  57. post_migrate = Signal(providing_args=["app_config", "verbosity", "interactive", "using"])