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

1from collections.abc import Callable 

2from typing import TYPE_CHECKING 

3 

4from plain.exceptions import ImproperlyConfigured 

5from plain.http import Response, ResponseRedirect 

6 

7from .templates import TemplateView 

8 

9if TYPE_CHECKING: 

10 from plain.forms import BaseForm 

11 

12 

13class FormView(TemplateView): 

14 """A view for displaying a form and rendering a template response.""" 

15 

16 form_class: type["BaseForm"] | None = None 

17 success_url: Callable | str | None = None 

18 

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

27 

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 } 

33 

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 

42 

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 

48 

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

52 

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) 

60 

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 

66 

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)