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