Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
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 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import functools
  2. from collections import Counter
  3. from pathlib import Path
  4. from django.apps import apps
  5. from django.conf import settings
  6. from django.core.exceptions import ImproperlyConfigured
  7. from django.utils.functional import cached_property
  8. from django.utils.module_loading import import_string
  9. class InvalidTemplateEngineError(ImproperlyConfigured):
  10. pass
  11. class EngineHandler:
  12. def __init__(self, templates=None):
  13. """
  14. templates is an optional list of template engine definitions
  15. (structured like settings.TEMPLATES).
  16. """
  17. self._templates = templates
  18. self._engines = {}
  19. @cached_property
  20. def templates(self):
  21. if self._templates is None:
  22. self._templates = settings.TEMPLATES
  23. templates = {}
  24. backend_names = []
  25. for tpl in self._templates:
  26. try:
  27. # This will raise an exception if 'BACKEND' doesn't exist or
  28. # isn't a string containing at least one dot.
  29. default_name = tpl["BACKEND"].rsplit(".", 2)[-2]
  30. except Exception:
  31. invalid_backend = tpl.get("BACKEND", "<not defined>")
  32. raise ImproperlyConfigured(
  33. "Invalid BACKEND for a template engine: {}. Check "
  34. "your TEMPLATES setting.".format(invalid_backend)
  35. )
  36. tpl = {
  37. "NAME": default_name,
  38. "DIRS": [],
  39. "APP_DIRS": False,
  40. "OPTIONS": {},
  41. **tpl,
  42. }
  43. templates[tpl["NAME"]] = tpl
  44. backend_names.append(tpl["NAME"])
  45. counts = Counter(backend_names)
  46. duplicates = [alias for alias, count in counts.most_common() if count > 1]
  47. if duplicates:
  48. raise ImproperlyConfigured(
  49. "Template engine aliases aren't unique, duplicates: {}. "
  50. "Set a unique NAME for each engine in settings.TEMPLATES.".format(
  51. ", ".join(duplicates)
  52. )
  53. )
  54. return templates
  55. def __getitem__(self, alias):
  56. try:
  57. return self._engines[alias]
  58. except KeyError:
  59. try:
  60. params = self.templates[alias]
  61. except KeyError:
  62. raise InvalidTemplateEngineError(
  63. "Could not find config for '{}' "
  64. "in settings.TEMPLATES".format(alias)
  65. )
  66. # If importing or initializing the backend raises an exception,
  67. # self._engines[alias] isn't set and this code may get executed
  68. # again, so we must preserve the original params. See #24265.
  69. params = params.copy()
  70. backend = params.pop("BACKEND")
  71. engine_cls = import_string(backend)
  72. engine = engine_cls(params)
  73. self._engines[alias] = engine
  74. return engine
  75. def __iter__(self):
  76. return iter(self.templates)
  77. def all(self):
  78. return [self[alias] for alias in self]
  79. @functools.lru_cache
  80. def get_app_template_dirs(dirname):
  81. """
  82. Return an iterable of paths of directories to load app templates from.
  83. dirname is the name of the subdirectory containing templates inside
  84. installed applications.
  85. """
  86. template_dirs = [
  87. Path(app_config.path) / dirname
  88. for app_config in apps.get_app_configs()
  89. if app_config.path and (Path(app_config.path) / dirname).is_dir()
  90. ]
  91. # Immutable return value because it will be cached and shared by callers.
  92. return tuple(template_dirs)