1from plain.csrf.middleware import get_token
2from plain.exceptions import ImproperlyConfigured
3from plain.runtime import settings
4from plain.templates import Template, TemplateFileMissing
5from plain.utils.functional import lazy
6from plain.utils.html import format_html
7from plain.utils.safestring import SafeString
8
9from .base import View
10
11
12def csrf_input(request):
13 return format_html(
14 '<input type="hidden" name="{}" value="{}">',
15 settings.CSRF_FIELD_NAME,
16 get_token(request),
17 )
18
19
20csrf_input_lazy = lazy(csrf_input, SafeString, str)
21csrf_token_lazy = lazy(get_token, str)
22
23
24class TemplateView(View):
25 """
26 Render a template.
27 """
28
29 template_name: str | None = None
30
31 def __init__(self, template_name=None):
32 # Allow template_name to be passed in as_view()
33 self.template_name = template_name or self.template_name
34
35 def get_template_context(self) -> dict:
36 return {
37 "request": self.request,
38 "template_names": self.get_template_names(),
39 "csrf_input": csrf_input_lazy(self.request),
40 "csrf_token": csrf_token_lazy(self.request),
41 "DEBUG": settings.DEBUG,
42 }
43
44 def get_template_names(self) -> list[str]:
45 """
46 Return a list of template names to be used for the request.
47 """
48 if self.template_name:
49 return [self.template_name]
50
51 return []
52
53 def get_template(self) -> Template:
54 template_names = self.get_template_names()
55
56 if not template_names:
57 raise ImproperlyConfigured(
58 f"{self.__class__.__name__} requires a template_name or get_template_names()."
59 )
60
61 for template_name in template_names:
62 try:
63 return Template(template_name)
64 except TemplateFileMissing:
65 pass
66
67 raise TemplateFileMissing(template_names)
68
69 def render_template(self) -> str:
70 return self.get_template().render(self.get_template_context())
71
72 def get(self):
73 return self.render_template()