web/views/forms.py
changeset 5385 b6e250dd7a7d
parent 5368 d321e4b62a10
child 5421 8167de96c523
--- a/web/views/forms.py	Fri Apr 23 11:10:30 2010 +0200
+++ b/web/views/forms.py	Fri Apr 23 12:42:53 2010 +0200
@@ -1,9 +1,32 @@
-"""some base form classes for CubicWeb web client
+# organization: Logilab
+# copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
+# contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+# license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
+"""
+Base form classes
+-----------------
+
+.. Note:
+
+   Form is the glue that bind a context to a set of fields, and is rendered
+   using a form renderer. No display is actually done here, though you'll find
+   some attributes of form that are used to control the rendering process.
 
-:organization: Logilab
-:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
-:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
-:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
+Besides the automagic form we'll see later, they are barely two form
+classes in |cubicweb|:
+
+.. autoclass:: cubicweb.web.views.forms.FieldsForm
+.. autoclass:: cubicweb.web.views.forms.EntityFieldsForm
+
+As you have probably guessed, choosing between them is easy. Simply ask you the
+question 'I am editing an entity or not?'. If the answer is yes, use
+:class:`EntityFieldsForm`, else use :class:`FieldsForm`.
+
+Actually there exists a third form class:
+
+.. autoclass:: cubicweb.web.views.forms.CompositeForm
+
+but you'll use this one rarely.
 """
 __docformat__ = "restructuredtext en"
 
@@ -16,43 +39,77 @@
 from cubicweb import typed_eid
 from cubicweb.selectors import non_final_entity, match_kwargs, one_line_rset
 from cubicweb.web import uicfg, form, formwidgets as fwdgs
-from cubicweb.web.formfields import StringField, relvoc_unrelated, guess_field
+from cubicweb.web.formfields import relvoc_unrelated, guess_field
 
 
 class FieldsForm(form.Form):
-    """base class for fields based forms.
+    """This is the base class for fields based forms.
+
+    **Attributes**
 
     The following attributes may be either set on subclasses or given on
     form selection to customize the generated form:
 
-    * `needs_js`: sequence of javascript files that should be added to handle
-      this form (through `req.add_js`)
+    :attr:`needs_js`
+      sequence of javascript files that should be added to handle this form
+      (through :meth:`~cubicweb.web.request.Request.add_js`)
 
-    * `needs_css`: sequence of css files that should be added to handle this
-      form (through `req.add_css`)
+    :attr:`needs_css`
+      sequence of css files that should be added to handle this form (through
+      :meth:`~cubicweb.web.request.Request.add_css`)
+
+    :attr:`domid`
+      value for the "id" attribute of the <form> tag
+
+    :attr:`action`
+      value for the "action" attribute of the <form> tag
 
-    * `domid`: value for the "id" attribute of the <form> tag
+    :attr:`onsubmit`
+      value for the "onsubmit" attribute of the <form> tag
 
-    * `action`: value for the "action" attribute of the <form> tag
+    :attr:`cssclass`
+      value for the "class" attribute of the <form> tag
 
-    * `onsubmit`: value for the "onsubmit" attribute of the <form> tag
+    :attr:`cssstyle`
+      value for the "style" attribute of the <form> tag
 
-    * `cssclass`: value for the "class" attribute of the <form> tag
+    :attr:`cwtarget`
+      value for the "cubicweb:target" attribute of the <form> tag
+
+    :attr:`redirect_path`
+      relative to redirect to after submitting the form
 
-    * `cssstyle`: value for the "style" attribute of the <form> tag
+    :attr:`copy_nav_params`
+      flag telling if navigation parameters should be copied back in hidden
+      inputs
+
+    :attr:`form_buttons`
+      sequence of form control (:class:`~cubicweb.web.formwidgets.Button`
+      widgets instances)
 
-    * `cwtarget`: value for the "cubicweb:target" attribute of the <form> tag
+    :attr:`form_renderer_id`
+      identifier of the form renderer to use to render the form
 
-    * `redirect_path`: relative to redirect to after submitting the form
+    :attr:`fieldsets_in_order`
+      sequence of fieldset names , to control order
+
+    **Generic methods**
 
-    * `copy_nav_params`: flag telling if navigation paramenters should be copied
-      back in hidden input
+    .. automethod:: cubicweb.web.form.Form.field_by_name(name, role=None)
+    .. automethod:: cubicweb.web.form.Form.fields_by_name(name, role=None)
+
+    **Form construction methods**
 
-    * `form_buttons`:  form buttons sequence (button widgets instances)
+    .. automethod:: cubicweb.web.form.Form.remove_field(field)
+    .. automethod:: cubicweb.web.form.Form.append_field(field)
+    .. automethod:: cubicweb.web.form.Form.insert_field_before(field, name, role=None)
+    .. automethod:: cubicweb.web.form.Form.insert_field_after(field, name, role=None)
+    .. automethod:: cubicweb.web.form.Form.add_hidden(name, value=None, **kwargs)
 
-    * `form_renderer_id`: id of the form renderer to use to render the form
+    **Form rendering methods**
 
-    * `fieldsets_in_order`: fieldset name sequence, to control order
+    .. automethod:: cubicweb.web.views.forms.FieldsForm.render
+
     """
     __regid__ = 'base'
 
@@ -75,18 +132,6 @@
         """true if the form needs enctype=multipart/form-data"""
         return any(field.needs_multipart for field in self.fields)
 
-    def add_hidden(self, name, value=None, **kwargs):
-        """add an hidden field to the form"""
-        kwargs.setdefault('ignore_req_params', True)
-        kwargs.setdefault('widget', fwdgs.HiddenInput)
-        field = StringField(name=name, value=value, **kwargs)
-        if 'id' in kwargs:
-            # by default, hidden input don't set id attribute. If one is
-            # explicitly specified, ensure it will be set
-            field.widget.setdomid = True
-        self.append_field(field)
-        return field
-
     def add_media(self):
         """adds media (CSS & JS) required by this widget"""
         if self.needs_js:
@@ -95,8 +140,16 @@
             self._cw.add_css(self.needs_css)
 
     def render(self, formvalues=None, rendervalues=None, renderer=None, **kwargs):
-        """render this form, using the renderer given in args or the default
-        FormRenderer()
+        """Render this form, using the `renderer` given as argument or the
+        default according to :attr:`form_renderer_id`. The rendered form is
+        returned as an unicode string.
+
+        `formvalues` is an optional dictionary containing values that will be
+        considered as field's value.
+
+        Extra keyword arguments will be given to renderer's :meth:`render` method.
+
+        `rendervalues` is deprecated.
         """
         if rendervalues is not None:
             warn('[3.6] rendervalues argument is deprecated, all named arguments will be given instead',
@@ -148,6 +201,11 @@
 _AFF_KWARGS = uicfg.autoform_field_kwargs
 
 class EntityFieldsForm(FieldsForm):
+    """This class is designed for forms used to edit some entities. It should
+    handle for you all the underlying stuff necessary to properly work with the
+    generic :class:`~cubicweb.web.views.editcontroller.EditController`.
+    """
+
     __regid__ = 'base'
     __select__ = (match_kwargs('entity')
                   | (one_line_rset() & non_final_entity()))
@@ -267,7 +325,6 @@
 
 
 class CompositeFormMixIn(object):
-    """form composed of sub-forms"""
     __regid__ = 'composite'
     form_renderer_id = __regid__
 
@@ -287,7 +344,9 @@
 
 
 class CompositeForm(CompositeFormMixIn, FieldsForm):
-    pass
+    """Form composed of sub-forms. Typical usage is edition of multiple entities
+    at once.
+    """
 
 class CompositeEntityForm(CompositeFormMixIn, EntityFieldsForm):
     pass # XXX why is this class necessary?