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.

deconstruct.py 1.9KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. from importlib import import_module
  2. from django.utils.version import get_docs_version
  3. def deconstructible(*args, path=None):
  4. """
  5. Class decorator that allows the decorated class to be serialized
  6. by the migrations subsystem.
  7. The `path` kwarg specifies the import path.
  8. """
  9. def decorator(klass):
  10. def __new__(cls, *args, **kwargs):
  11. # We capture the arguments to make returning them trivial
  12. obj = super(klass, cls).__new__(cls)
  13. obj._constructor_args = (args, kwargs)
  14. return obj
  15. def deconstruct(obj):
  16. """
  17. Return a 3-tuple of class import path, positional arguments,
  18. and keyword arguments.
  19. """
  20. # Fallback version
  21. if path:
  22. module_name, _, name = path.rpartition('.')
  23. else:
  24. module_name = obj.__module__
  25. name = obj.__class__.__name__
  26. # Make sure it's actually there and not an inner class
  27. module = import_module(module_name)
  28. if not hasattr(module, name):
  29. raise ValueError(
  30. "Could not find object %s in %s.\n"
  31. "Please note that you cannot serialize things like inner "
  32. "classes. Please move the object into the main module "
  33. "body to use migrations.\n"
  34. "For more information, see "
  35. "https://docs.djangoproject.com/en/%s/topics/migrations/#serializing-values"
  36. % (name, module_name, get_docs_version()))
  37. return (
  38. path or '%s.%s' % (obj.__class__.__module__, name),
  39. obj._constructor_args[0],
  40. obj._constructor_args[1],
  41. )
  42. klass.__new__ = staticmethod(__new__)
  43. klass.deconstruct = deconstruct
  44. return klass
  45. if not args:
  46. return decorator
  47. return decorator(*args)