Plain is headed towards 1.0! Subscribe for development updates →

Forms

Handle user input.

  • forms don't render themselves
  • registered scripts vs media?
  • move model save logic into form.save() - disconnect them
  • Form: validates input from request, saves it
  • Form field: validates field, knows how to parse from html data ?
  • starter includes form components - no markup in python

Re-using input styles

plain-elements, or includes

 1from functools import cached_property
 2
 3__all__ = ("BoundField",)
 4
 5
 6class BoundField:
 7    "A Field plus data"
 8
 9    def __init__(self, form, field, name):
10        self._form = form
11        self.field = field
12        self.name = name
13        self.html_name = form.add_prefix(name)
14        self.html_id = form.add_prefix(self._auto_id)
15
16    def __repr__(self):
17        return f'<{self.__class__.__name__} "{self.html_name}">'
18
19    @property
20    def errors(self):
21        """
22        Return an error list (empty if there are no errors) for this field.
23        """
24        return self._form.errors.get(self.name, [])
25
26    def value(self):
27        """
28        Return the value for this BoundField, using the initial value if
29        the form is not bound or the data otherwise.
30        """
31        data = self.initial
32        if self._form.is_bound:
33            data = self.field.bound_data(
34                self._form._field_data_value(self.field, self.html_name), data
35            )
36        return self.field.prepare_value(data)
37
38    @cached_property
39    def initial(self):
40        return self._form.get_initial_for_field(self.field, self.name)
41
42    def _has_changed(self):
43        return self.field.has_changed(
44            self.initial, self._form._field_data_value(self.field, self.html_name)
45        )
46
47    @property
48    def _auto_id(self):
49        """
50        Calculate and return the ID attribute for this BoundField, if the
51        associated Form has specified auto_id. Return an empty string otherwise.
52        """
53        auto_id = self._form._auto_id  # Boolean or string
54        if auto_id and "%s" in str(auto_id):
55            return auto_id % self.html_name
56        elif auto_id:
57            return self.html_name
58        return ""