renderers.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import functools
  2. import warnings
  3. from pathlib import Path
  4. from django.conf import settings
  5. from django.template.backends.django import DjangoTemplates
  6. from django.template.loader import get_template
  7. from django.utils.deprecation import RemovedInDjango60Warning
  8. from django.utils.functional import cached_property
  9. from django.utils.module_loading import import_string
  10. @functools.lru_cache
  11. def get_default_renderer():
  12. renderer_class = import_string(settings.FORM_RENDERER)
  13. return renderer_class()
  14. class BaseRenderer:
  15. form_template_name = "django/forms/div.html"
  16. formset_template_name = "django/forms/formsets/div.html"
  17. field_template_name = "django/forms/field.html"
  18. def get_template(self, template_name):
  19. raise NotImplementedError("subclasses must implement get_template()")
  20. def render(self, template_name, context, request=None):
  21. template = self.get_template(template_name)
  22. return template.render(context, request=request).strip()
  23. class EngineMixin:
  24. def get_template(self, template_name):
  25. return self.engine.get_template(template_name)
  26. @cached_property
  27. def engine(self):
  28. return self.backend(
  29. {
  30. "APP_DIRS": True,
  31. "DIRS": [Path(__file__).parent / self.backend.app_dirname],
  32. "NAME": "djangoforms",
  33. "OPTIONS": {},
  34. }
  35. )
  36. class DjangoTemplates(EngineMixin, BaseRenderer):
  37. """
  38. Load Django templates from the built-in widget templates in
  39. django/forms/templates and from apps' 'templates' directory.
  40. """
  41. backend = DjangoTemplates
  42. class Jinja2(EngineMixin, BaseRenderer):
  43. """
  44. Load Jinja2 templates from the built-in widget templates in
  45. django/forms/jinja2 and from apps' 'jinja2' directory.
  46. """
  47. @cached_property
  48. def backend(self):
  49. from django.template.backends.jinja2 import Jinja2
  50. return Jinja2
  51. # RemovedInDjango60Warning.
  52. class DjangoDivFormRenderer(DjangoTemplates):
  53. """
  54. Load Django templates from django/forms/templates and from apps'
  55. 'templates' directory and use the 'div.html' template to render forms and
  56. formsets.
  57. """
  58. def __init__(self, *args, **kwargs):
  59. warnings.warn(
  60. "The DjangoDivFormRenderer transitional form renderer is deprecated. Use "
  61. "DjangoTemplates instead.",
  62. RemovedInDjango60Warning,
  63. )
  64. super().__init__(*args, **kwargs)
  65. # RemovedInDjango60Warning.
  66. class Jinja2DivFormRenderer(Jinja2):
  67. """
  68. Load Jinja2 templates from the built-in widget templates in
  69. django/forms/jinja2 and from apps' 'jinja2' directory.
  70. """
  71. def __init__(self, *args, **kwargs):
  72. warnings.warn(
  73. "The Jinja2DivFormRenderer transitional form renderer is deprecated. Use "
  74. "Jinja2 instead.",
  75. RemovedInDjango60Warning,
  76. )
  77. super().__init__(*args, **kwargs)
  78. class TemplatesSetting(BaseRenderer):
  79. """
  80. Load templates using template.loader.get_template() which is configured
  81. based on settings.TEMPLATES.
  82. """
  83. def get_template(self, template_name):
  84. return get_template(template_name)