Plain is headed towards 1.0! Subscribe for development updates →

 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())