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 ""