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.

utils.py 2.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import functools
  2. from importlib import import_module
  3. from django.core.exceptions import ViewDoesNotExist
  4. from django.utils.module_loading import module_has_submodule
  5. @functools.lru_cache(maxsize=None)
  6. def get_callable(lookup_view):
  7. """
  8. Return a callable corresponding to lookup_view.
  9. * If lookup_view is already a callable, return it.
  10. * If lookup_view is a string import path that can be resolved to a callable,
  11. import that callable and return it, otherwise raise an exception
  12. (ImportError or ViewDoesNotExist).
  13. """
  14. if callable(lookup_view):
  15. return lookup_view
  16. if not isinstance(lookup_view, str):
  17. raise ViewDoesNotExist("'%s' is not a callable or a dot-notation path" % lookup_view)
  18. mod_name, func_name = get_mod_func(lookup_view)
  19. if not func_name: # No '.' in lookup_view
  20. raise ImportError("Could not import '%s'. The path must be fully qualified." % lookup_view)
  21. try:
  22. mod = import_module(mod_name)
  23. except ImportError:
  24. parentmod, submod = get_mod_func(mod_name)
  25. if submod and not module_has_submodule(import_module(parentmod), submod):
  26. raise ViewDoesNotExist(
  27. "Could not import '%s'. Parent module %s does not exist." %
  28. (lookup_view, mod_name)
  29. )
  30. else:
  31. raise
  32. else:
  33. try:
  34. view_func = getattr(mod, func_name)
  35. except AttributeError:
  36. raise ViewDoesNotExist(
  37. "Could not import '%s'. View does not exist in module %s." %
  38. (lookup_view, mod_name)
  39. )
  40. else:
  41. if not callable(view_func):
  42. raise ViewDoesNotExist(
  43. "Could not import '%s.%s'. View is not callable." %
  44. (mod_name, func_name)
  45. )
  46. return view_func
  47. def get_mod_func(callback):
  48. # Convert 'django.views.news.stories.story_detail' to
  49. # ['django.views.news.stories', 'story_detail']
  50. try:
  51. dot = callback.rindex('.')
  52. except ValueError:
  53. return callback, ''
  54. return callback[:dot], callback[dot + 1:]