Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/deform/form.py : 20%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Form."""
2# Standard Library
3import re
5from chameleon.utils import Markup
7from . import compat
8from . import field
9from . import widget
12class Form(field.Field):
13 """
14 Field representing an entire form.
16 Arguments:
18 schema
19 A :class:`colander.SchemaNode` object representing a
20 schema to be rendered. Required.
22 action
23 The form action (inserted into the ``action`` attribute of
24 the form's form tag when rendered). Default: the empty string.
26 method
27 The form method (inserted into the ``method`` attribute of
28 the form's form tag when rendered). Default: ``POST``.
30 buttons
31 A sequence of strings or :class:`deform.form.Button`
32 objects representing submit buttons that will be placed at
33 the bottom of the form. If any string is passed in the
34 sequence, it is converted to
35 :class:`deform.form.Button` objects.
37 formid
38 The identifier for this form. This value will be used as the
39 HTML ``id`` attribute of the rendered HTML form. It will also
40 be used as the value of a hidden form input control
41 (``__formid__``) which will be placed in this form's
42 rendering. You should pass a string value for ``formid`` when
43 more than one Deform form is placed into a single page and
44 both share the same action. When one of the forms on the page
45 is posted, your code will to be able to decide which of those
46 forms was posted based on the differing values of
47 ``__formid__``. By default, ``formid`` is ``deform``.
49 autocomplete
50 Controls this form's ``autocomplete`` attribute. If ``autocomplete``
51 is ``None``, no autocomplete attribute will be added to the form tag.
52 If ``autocomplete`` is a true value, an ``autocomplete='on'``
53 attribute will be added to the form tag. If ``autocomplete`` is a
54 false value, an ``autocomplete='off'`` attribute will be added to the
55 form tag. Default: ``None``.
57 focus
58 Determines this form's input focus.
60 - If ``focus`` is ``on``, and at least one field has an ``autofocus``
61 schema parameter set to ``on``, the first of these fields will
62 receive focus on page load.
63 - If ``focus`` is ``on`` or omitted, and no field has an
64 ``autofocus`` schema parameter set to ``on``, the first input of
65 the first form on the page will receive focus on page load.
66 - If ``focus`` is ``off``, no focusing will be done.
68 Default: ``on``.
70 use_ajax
71 If this option is ``True``, the form will use AJAX (actually
72 AJAH); when any submit button is clicked, the DOM node related
73 to this form will be replaced with the result of the form post
74 caused by the submission. The page will not be reloaded. This
75 feature uses the ``jquery.form`` library ``ajaxForm`` feature
76 as per `http://jquery.malsup.com/form/
77 <http://jquery.malsup.com/form/>`_. Default: ``False``. If
78 this option is ``True``, the ``jquery.form.js`` library must be
79 loaded in the HTML page which embeds the form. A copy of it
80 exists in the ``static`` directory of the ``deform`` package.
82 ajax_options
83 A *string* which must represent a JavaScript object
84 (dictionary) of extra AJAX options as per
85 `http://jquery.malsup.com/form/#tab3
86 <http://jquery.malsup.com/form/#tab3>`_. For
87 example:
89 .. code-block:: python
91 '{"success": function (rText, sText, xhr, form) {alert(sText)};}'
93 Default options exist even if ``ajax_options`` is not provided.
94 By default, ``target`` points at the DOM node representing the
95 form and and ``replaceTarget`` is ``true``.
97 A success handler calls the ``deform.processCallbacks`` method
98 that will ajaxify the newly written form again. If you pass
99 these values in ``ajax_options``, the defaults will be
100 overridden. If you want to override the success handler, don't
101 forget to call ``deform.processCallbacks``, otherwise
102 subsequent form submissions won't be submitted via AJAX.
104 This option has no effect when ``use_ajax`` is False.
106 The default value of ``ajax_options`` is a string
107 representation of the empty object.
109 The :class:`deform.Form` constructor also accepts all the keyword
110 arguments accepted by the :class:`deform.Field` class. These
111 keywords mean the same thing in the context of a Form as they do
112 in the context of a Field (a Form is just another kind of Field).
113 """
115 css_class = "deform" # bw compat only; pass a widget to override
117 def __init__(
118 self,
119 schema,
120 action="",
121 method="POST",
122 buttons=(),
123 formid="deform",
124 use_ajax=False,
125 ajax_options="{}",
126 autocomplete=None,
127 focus="on",
128 **kw
129 ):
130 if autocomplete:
131 autocomplete = "on"
132 elif autocomplete is not None:
133 autocomplete = "off"
134 self.autocomplete = autocomplete
135 if str(focus).lower() == "off":
136 self.focus = "off"
137 else:
138 self.focus = "on"
139 # Use kwargs to pass flags to descendant fields; saves cluttering
140 # the constructor
141 kw["focus"] = self.focus
142 field.Field.__init__(self, schema, **kw)
143 _buttons = []
144 for button in buttons:
145 if isinstance(button, compat.string_types):
146 button = Button(button)
147 _buttons.append(button)
148 self.action = action
149 self.method = method
150 self.buttons = _buttons
151 self.formid = formid
152 self.use_ajax = use_ajax
153 self.ajax_options = Markup(ajax_options.strip())
154 form_widget = getattr(schema, "widget", None)
155 if form_widget is None:
156 form_widget = widget.FormWidget()
157 self.widget = form_widget
160class Button(object):
161 """
162 A class representing a form submit button. A sequence of
163 :class:`deform.widget.Button` objects may be passed to the
164 constructor of a :class:`deform.form.Form` class when it is
165 created to represent the buttons renderered at the bottom of the
166 form.
168 Arguments:
170 name
171 The string or unicode value used as the ``name`` of the button
172 when rendered (the ``name`` attribute of the button or input
173 tag resulting from a form rendering). Default: ``submit``.
175 title
176 The value used as the title of the button when rendered (shows
177 up in the button inner text). Default: capitalization of
178 whatever is passed as ``name``. E.g. if ``name`` is passed as
179 ``submit``, ``title`` will be ``Submit``.
181 type
182 The value used as the type of button. The HTML spec supports
183 ``submit``, ``reset`` and ``button``. A special value of
184 ``link`` will create a regular HTML link that's styled to look
185 like a button. Default: ``submit``.
187 value
188 The value used as the value of the button when rendered (the
189 ``value`` attribute of the button or input tag resulting from
190 a form rendering). If the button ``type`` is ``link`` then
191 this setting is used as the URL for the link button.
192 Default: same as ``name`` passed.
194 icon
195 glyph icon name to include as part of button. (Ex. If you
196 wanted to add the glyphicon-plus to this button then you'd pass
197 in a value of ``plus``) Default: ``None`` (no icon is added)
199 disabled
200 Render the button as disabled if True.
202 css_class
203 The name of a CSS class to attach to the button. In the default
204 form rendering, this string will replace the default button type
205 (either ``btn-primary`` or ``btn-default``) on the the ``class``
206 attribute of the button. For example, if ``css_class`` was
207 ``btn-danger`` then the resulting default class becomes
208 ``btn btn-danger``. Default: ``None`` (use default class).
210 attributes
211 HTML5 attributes passed in as a dictionary. This is especially
212 useful for a Cancel button where you do not want the client to
213 validate the form inputs, for example
214 ``attributes={"formnovalidate": "formnovalidate"}``.
215 """
217 def __init__(
218 self,
219 name="submit",
220 title=None,
221 type="submit", # noQA
222 value=None,
223 disabled=False,
224 css_class=None,
225 icon=None,
226 attributes=None,
227 ):
228 if attributes is None:
229 attributes = {}
230 if title is None:
231 title = name.capitalize()
232 name = re.sub(r"\s", "_", name)
233 if value is None and type != "link":
234 value = name
235 self.name = name
236 self.title = title
237 self.type = type # noQA
238 self.value = value
239 self.disabled = disabled
240 self.css_class = css_class
241 self.icon = icon
242 self.attributes = attributes