Coverage for /Users/davegaeddert/Developer/dropseed/plain/plain/plain/views/forms.py: 43%
37 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-23 11:16 -0600
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-23 11:16 -0600
1from collections.abc import Callable
2from typing import TYPE_CHECKING
4from plain.exceptions import ImproperlyConfigured
5from plain.http import Response, ResponseRedirect
7from .templates import TemplateView
9if TYPE_CHECKING:
10 from plain.forms import BaseForm
13class FormView(TemplateView):
14 """A view for displaying a form and rendering a template response."""
16 form_class: type["BaseForm"] | None = None
17 success_url: Callable | str | None = None
19 def get_form(self) -> "BaseForm":
20 """Return an instance of the form to be used in this view."""
21 if not self.form_class:
22 raise ImproperlyConfigured(
23 f"No form class provided. Define {self.__class__.__name__}.form_class or override "
24 f"{self.__class__.__name__}.get_form()."
25 )
26 return self.form_class(**self.get_form_kwargs())
28 def get_form_kwargs(self) -> dict:
29 """Return the keyword arguments for instantiating the form."""
30 kwargs: dict = {
31 "initial": {}, # Make it easier to set keys in subclasses
32 }
34 if hasattr(self, "request") and self.request.method in ("POST", "PUT"):
35 kwargs.update(
36 {
37 "data": self.request.POST,
38 "files": self.request.FILES,
39 }
40 )
41 return kwargs
43 def get_success_url(self) -> str:
44 """Return the URL to redirect to after processing a valid form."""
45 if not self.success_url:
46 raise ImproperlyConfigured("No URL to redirect to. Provide a success_url.")
47 return str(self.success_url) # success_url may be lazy
49 def form_valid(self, form: "BaseForm") -> Response:
50 """If the form is valid, redirect to the supplied URL."""
51 return ResponseRedirect(self.get_success_url())
53 def form_invalid(self, form: "BaseForm") -> Response:
54 """If the form is invalid, render the invalid form."""
55 context = {
56 **self.get_template_context(),
57 "form": form,
58 }
59 return self.get_template().render(context)
61 def get_template_context(self) -> dict:
62 """Insert the form into the context dict."""
63 context = super().get_template_context()
64 context["form"] = self.get_form()
65 return context
67 def post(self) -> Response:
68 """
69 Handle POST requests: instantiate a form instance with the passed
70 POST variables and then check if it's valid.
71 """
72 form = self.get_form()
73 if form.is_valid():
74 return self.form_valid(form)
75 else:
76 return self.form_invalid(form)