[Checkins] SVN: z3c.formui/tags/2.1.0/ Tag 2.1.0

Dan Korostelev nadako at gmail.com
Tue Sep 1 14:23:39 EDT 2009


Log message for revision 103465:
  Tag 2.1.0

Changed:
  A   z3c.formui/tags/2.1.0/
  D   z3c.formui/tags/2.1.0/CHANGES.txt
  A   z3c.formui/tags/2.1.0/CHANGES.txt
  U   z3c.formui/tags/2.1.0/setup.py
  D   z3c.formui/tags/2.1.0/src/z3c/formui/README.txt
  A   z3c.formui/tags/2.1.0/src/z3c/formui/README.txt

-=-
Deleted: z3c.formui/tags/2.1.0/CHANGES.txt
===================================================================
--- z3c.formui/trunk/CHANGES.txt	2009-09-01 18:06:50 UTC (rev 103463)
+++ z3c.formui/tags/2.1.0/CHANGES.txt	2009-09-01 18:23:39 UTC (rev 103465)
@@ -1,130 +0,0 @@
-=======
-CHANGES
-=======
-
-2.1.0 (unreleased)
-------------------
-
-- Feature: Don't show required info hint if there's no required fields.
-
-- Bug: Don't render add forms when redirecting as well.
-
-2.0.0 (2009-06-14)
-------------------
-
-- Feature: Added support for context-specific template lookup, introduced in
-  `z3c.template` 1.2.0 - templates can now be registered using (view, request,
-  context) discriminator.
-
-- Feature: Added support for `z3c.pt` templates using `z3c.ptcompat`
-  compatibility package.
-
-- Feature: Added layout support for `IAdding` component based add forms.
-
-- Feature: Added CSS for multi-widget which was added in `z3c.form` 2.0.0.
-
-- Bug: Changed usage of ``template/macros/*`` to ``macro:*``, because the
-  first one doesn't work when we override a form template and use the form
-  macro, registered with this package.
-
-- Bug: Don't do rendering in form's `__call__` method when request is a
-  redirection.
-
-- Bug: Reformatted long-description to render properly on pypi.
-
-
-1.4.2 (2008-08-26)
-------------------
-
-- Bug: Corrected typos and unwanted unicode characters.
-
-
-1.4.1 (2008-01-23)
-------------------
-
-- Bug: Fixed up meta-data and the release.
-
-
-1.4.0 (2008-01-21)
-------------------
-
-- Feature: Added subform content and layout template. This allows you to
-  configure real sub forms which do not render the form tag.
-
-- Feature: Improve layout implementation, support built-in layout templates.
-
-- Feature: Use ``IContentTemplate`` instead of ``IPageTemplate`` in layout
-  base classes. This will help to prevent running into recursion errors if
-  there is a missing layout template.
-
-- Feature: Added form module which offers built-in layout support.
-
-- Bug: Added missing display ``IContentTemplate``, otherwise we can run into a
-  recursion in some cases.
-
-- Bug: Renamed table macro argument from ``form-required-info`` to
-  ``required-info``. The macro ``form-required-info`` did not exist.
-
-- Bug: Added unit tests for layout support.
-
-- Bug: Added tests for layout macros.
-
-- Bug: Added tests for layout templates.
-
-
-1.3.0 (2007-08-24)
-------------------
-
-- Refactoring: Update CSS classes to reflect latest changes to the widget
-  classes in ``z3c.form``.
-
-- Bug: Error view snippets may have a empty ``widget`` attribute values, so we
-  cannot rely on accessing the label of the widget. This is the case, if the
-  error view sniipet was created from an invariants validation error.
-
-- Bug: The table-form template did not properly render the error at the
-  widget, because the ``render()`` method was not called. Thanks to Markus
-  Leist for the report.
-
-
-1.2.0 (2007-07-18)
-------------------
-
-- Feature: The row div element now also has an id of the form
-  "<widget-id>-row".
-
-
-1.1.1 (2007-07-04)
-------------------
-
-- Refactoring: Split up registrations for simpler management of UI
-  components. This also makes it easier to see for developers how to create a
-  new template for forms.
-
-
-1.1.0 (2007-06-29)
-------------------
-
-- Feature: Registered all defined macros for each form template. Also, added
-  more slots to the templates providing more hooks for customization.
-
-- Feature: Added a macro/slot for the "required info", which explains how
-  required fields are marked.
-
-- Feature: Added support for form labels.
-
-- Feature: Added support for groups to templates.
-
-
-1.0.1 (2007-06-22)
-------------------
-
-- Bug: Make sure we use the id for the "for" attribute of the "label"
-  element and not the name. This has worked until recently, because the
-  name and id were the same, but they are different now.
-
-
-1.0.0 (2007-05-24)
-------------------
-
-- Initial Release

Copied: z3c.formui/tags/2.1.0/CHANGES.txt (from rev 103464, z3c.formui/trunk/CHANGES.txt)
===================================================================
--- z3c.formui/tags/2.1.0/CHANGES.txt	                        (rev 0)
+++ z3c.formui/tags/2.1.0/CHANGES.txt	2009-09-01 18:23:39 UTC (rev 103465)
@@ -0,0 +1,133 @@
+=======
+CHANGES
+=======
+
+2.1.0 (2009-09-01)
+------------------
+
+- Feature: Don't show required info hint if there's no required fields.
+
+- Bug: Don't render add forms when redirecting as well.
+
+- Bug: Fix redirection tests with newer zope.publisher that restricts
+  untrusted redirects to different domains.
+
+2.0.0 (2009-06-14)
+------------------
+
+- Feature: Added support for context-specific template lookup, introduced in
+  `z3c.template` 1.2.0 - templates can now be registered using (view, request,
+  context) discriminator.
+
+- Feature: Added support for `z3c.pt` templates using `z3c.ptcompat`
+  compatibility package.
+
+- Feature: Added layout support for `IAdding` component based add forms.
+
+- Feature: Added CSS for multi-widget which was added in `z3c.form` 2.0.0.
+
+- Bug: Changed usage of ``template/macros/*`` to ``macro:*``, because the
+  first one doesn't work when we override a form template and use the form
+  macro, registered with this package.
+
+- Bug: Don't do rendering in form's `__call__` method when request is a
+  redirection.
+
+- Bug: Reformatted long-description to render properly on pypi.
+
+
+1.4.2 (2008-08-26)
+------------------
+
+- Bug: Corrected typos and unwanted unicode characters.
+
+
+1.4.1 (2008-01-23)
+------------------
+
+- Bug: Fixed up meta-data and the release.
+
+
+1.4.0 (2008-01-21)
+------------------
+
+- Feature: Added subform content and layout template. This allows you to
+  configure real sub forms which do not render the form tag.
+
+- Feature: Improve layout implementation, support built-in layout templates.
+
+- Feature: Use ``IContentTemplate`` instead of ``IPageTemplate`` in layout
+  base classes. This will help to prevent running into recursion errors if
+  there is a missing layout template.
+
+- Feature: Added form module which offers built-in layout support.
+
+- Bug: Added missing display ``IContentTemplate``, otherwise we can run into a
+  recursion in some cases.
+
+- Bug: Renamed table macro argument from ``form-required-info`` to
+  ``required-info``. The macro ``form-required-info`` did not exist.
+
+- Bug: Added unit tests for layout support.
+
+- Bug: Added tests for layout macros.
+
+- Bug: Added tests for layout templates.
+
+
+1.3.0 (2007-08-24)
+------------------
+
+- Refactoring: Update CSS classes to reflect latest changes to the widget
+  classes in ``z3c.form``.
+
+- Bug: Error view snippets may have a empty ``widget`` attribute values, so we
+  cannot rely on accessing the label of the widget. This is the case, if the
+  error view sniipet was created from an invariants validation error.
+
+- Bug: The table-form template did not properly render the error at the
+  widget, because the ``render()`` method was not called. Thanks to Markus
+  Leist for the report.
+
+
+1.2.0 (2007-07-18)
+------------------
+
+- Feature: The row div element now also has an id of the form
+  "<widget-id>-row".
+
+
+1.1.1 (2007-07-04)
+------------------
+
+- Refactoring: Split up registrations for simpler management of UI
+  components. This also makes it easier to see for developers how to create a
+  new template for forms.
+
+
+1.1.0 (2007-06-29)
+------------------
+
+- Feature: Registered all defined macros for each form template. Also, added
+  more slots to the templates providing more hooks for customization.
+
+- Feature: Added a macro/slot for the "required info", which explains how
+  required fields are marked.
+
+- Feature: Added support for form labels.
+
+- Feature: Added support for groups to templates.
+
+
+1.0.1 (2007-06-22)
+------------------
+
+- Bug: Make sure we use the id for the "for" attribute of the "label"
+  element and not the name. This has worked until recently, because the
+  name and id were the same, but they are different now.
+
+
+1.0.0 (2007-05-24)
+------------------
+
+- Initial Release

Modified: z3c.formui/tags/2.1.0/setup.py
===================================================================
--- z3c.formui/trunk/setup.py	2009-09-01 18:06:50 UTC (rev 103463)
+++ z3c.formui/tags/2.1.0/setup.py	2009-09-01 18:23:39 UTC (rev 103465)
@@ -23,7 +23,7 @@
 
 setup (
     name='z3c.formui',
-    version='2.1.0dev',
+    version='2.1.0',
     author = "Stephan Richter, Roger Ineichen and the Zope Community",
     author_email = "zope-dev at zope.org",
     description = "A set of initial UI components for z3c.form.",

Deleted: z3c.formui/tags/2.1.0/src/z3c/formui/README.txt
===================================================================
--- z3c.formui/trunk/src/z3c/formui/README.txt	2009-09-01 18:06:50 UTC (rev 103463)
+++ z3c.formui/tags/2.1.0/src/z3c/formui/README.txt	2009-09-01 18:23:39 UTC (rev 103465)
@@ -1,909 +0,0 @@
-====================
-Form User Interfaces
-====================
-
-This package provides several useful templates to get a quick start with the
-``z3c.form`` package. Previous form frameworks always included default
-templates that were implemented in a particular user-interface development
-pattern. If you wanted to use an alternative strategy to develop user
-interfaces, it was often tedious to do so. This package aims to provide some
-options without requiring them for the basic framework.
-
-
-Layout Template Support
------------------------
-
-One common pattern in Zope 3 user interface development is the use of layout
-templates (see z3c.template). This package provides some mixin classes to the
-regular form classes to support layout-based templating.
-
-  >>> from z3c.form import testing
-  >>> testing.setupFormDefaults()
-
-Before we can start writing forms, we must have the content to work with:
-
-  >>> import zope.interface
-  >>> import zope.schema
-  >>> class IPerson(zope.interface.Interface):
-  ...
-  ...     name = zope.schema.TextLine(
-  ...         title=u'Name',
-  ...         required=True)
-  ...
-  ...     age = zope.schema.Int(
-  ...         title=u'Age',
-  ...         description=u"The person's age.",
-  ...         min=0,
-  ...         default=20,
-  ...         required=False)
-
-  >>> from zope.schema.fieldproperty import FieldProperty
-  >>> class Person(object):
-  ...     zope.interface.implements(IPerson)
-  ...
-  ...     name = FieldProperty(IPerson['name'])
-  ...     age = FieldProperty(IPerson['age'])
-  ...
-  ...     def __init__(self, name, age):
-  ...         self.name = name
-  ...         self.age = age
-  ...
-  ...     def __repr__(self):
-  ...         return '<%s %r>' % (self.__class__.__name__, self.name)
-
-Okay, that should suffice for now. Let's now create a working add form:
-
-  >>> from z3c.form import field
-  >>> from z3c.formui import form, layout
-  >>> class PersonAddForm(form.AddForm):
-  ...
-  ...     fields = field.Fields(IPerson)
-  ...
-  ...     def create(self, data):
-  ...         return Person(**data)
-  ...
-  ...     def add(self, object):
-  ...         self.context[object.id] = object
-  ...
-  ...     def nextURL(self):
-  ...         return 'index.html'
-
-Let's create a request:
-
-  >>> from z3c.form.testing import TestRequest
-  >>> from zope.interface import alsoProvides
-  >>> divRequest = TestRequest()
-
-And support the div form layer for our request:
-
-  >>> from z3c.formui.interfaces import IDivFormLayer
-  >>> alsoProvides(divRequest, IDivFormLayer)
-
-Now create the form:
-
-  >>> addForm = PersonAddForm(root, divRequest)
-
-Since we have not specified a template yet, we have to do this now. We use our
-div based form template:
-
-  >>> import os
-  >>> import z3c.formui
-  >>> divFormTemplate = os.path.join(os.path.dirname(z3c.formui.__file__),
-  ...     'div-form.pt')
-
-  >>> from z3c.template.template import TemplateFactory
-  >>> divFormFactory = TemplateFactory(divFormTemplate, 'text/html')
-
-Now register the form (content) template:
-
-  >>> import zope.interface
-  >>> import zope.component
-  >>> from z3c.template.interfaces import IContentTemplate
-  >>> zope.component.provideAdapter(divFormFactory,
-  ...     (zope.interface.Interface, IDivFormLayer),
-  ...     IContentTemplate)
-
-And let's define a layout template which simply calls the render method. For a
-more advanced content/layout render concept see z3c.pagelet.
-
-  >>> import tempfile
-  >>> temp_dir = tempfile.mkdtemp()
-
-  >>> myLayout = os.path.join(temp_dir, 'myLayout.pt')
-  >>> open(myLayout, 'w').write('''<html>
-  ...   <body>
-  ...     <tal:block content="structure view/render">
-  ...       content
-  ...     </tal:block>
-  ...   </body>
-  ... </html>''')
-  >>> myLayoutFactory = TemplateFactory(myLayout, 'text/html')
-
-  >>> from z3c.template.interfaces import ILayoutTemplate
-  >>> zope.component.provideAdapter(myLayoutFactory,
-  ...     (zope.interface.Interface, zope.interface.Interface), ILayoutTemplate)
-
-Now we can get our layout template:
-
-  >>> layout = zope.component.getMultiAdapter((addForm, divRequest),
-  ...     ILayoutTemplate)
-
-  >>> from z3c import ptcompat
-  >>> isinstance(layout, ptcompat.ViewPageTemplateFile)
-  True
-
-
-DIV-based Layout
-----------------
-
-Let's now render the page. Note the output doesn't contain the layout template:
-
-  >>> addForm.update()
-  >>> print addForm.render()
-  <form action="http://127.0.0.1" method="post"
-          enctype="multipart/form-data" class="edit-form"
-          name="form" id="form">
-    <div class="viewspace">
-      <div class="required-info">
-        <span class="required">*</span> &ndash; required
-      </div>
-      <div>
-        <div id="form-widgets-name-row" class="row">
-          <div class="label">
-            <label for="form-widgets-name">
-              <span>Name</span>
-              <span class="required">*</span>
-            </label>
-          </div>
-          <div class="widget"><input type="text" id="form-widgets-name"
-                   name="form.widgets.name"
-                   class="text-widget required textline-field" value="" />
-          </div>
-        </div>
-        <div id="form-widgets-age-row" class="row">
-          <div class="label">
-            <label for="form-widgets-age">
-              <span>Age</span>
-            </label>
-          </div>
-          <div class="widget"><input type="text" id="form-widgets-age"
-                   name="form.widgets.age" class="text-widget int-field"
-                   value="20" />
-          </div>
-        </div>
-      </div>
-    </div>
-    <div>
-      <div class="buttons">
-        <input type="submit" id="form-buttons-add"
-               name="form.buttons.add"
-               class="submit-widget button-field" value="Add" />
-      </div>
-    </div>
-  </form>
-
-But we can call our form which uses the new layout template which renders
-the form within the div-form content template:
-
-  >>> print addForm()
-  <html>
-    <body>
-      <form action="http://127.0.0.1" method="post"
-        enctype="multipart/form-data" class="edit-form"
-        name="form" id="form">
-        <div class="viewspace">
-          <div class="required-info">
-            <span class="required">*</span>
-            &ndash; required
-          </div>
-          <div>
-            <div id="form-widgets-name-row" class="row">
-              <div class="label">
-                <label for="form-widgets-name">
-                  <span>Name</span>
-                  <span class="required">*</span>
-                </label>
-              </div>
-              <div class="widget"><input type="text" id="form-widgets-name"
-                   name="form.widgets.name"
-                   class="text-widget required textline-field" value="" />
-              </div>
-            </div>
-            <div id="form-widgets-age-row" class="row">
-              <div class="label">
-                <label for="form-widgets-age">
-                  <span>Age</span>
-                </label>
-              </div>
-              <div class="widget"><input type="text" id="form-widgets-age"
-                   name="form.widgets.age" class="text-widget int-field"
-                   value="20" />
-              </div>
-            </div>
-          </div>
-        </div>
-        <div>
-          <div class="buttons">
-            <input type="submit" id="form-buttons-add"
-             name="form.buttons.add"
-             class="submit-widget button-field" value="Add" />
-          </div>
-        </div>
-      </form>
-    </body>
-  </html>
-
-
-Table-based Forms
------------------
-
-There is a table based layout too. Let's define the template and use them:
-
-  >>> from z3c.formui.interfaces import ITableFormLayer
-  >>> tableFormTemplate = os.path.join(os.path.dirname(z3c.formui.__file__),
-  ...     'table-form.pt')
-
-  >>> from z3c.template.template import TemplateFactory
-  >>> tableFormFactory = TemplateFactory(tableFormTemplate, 'text/html')
-
-Now register the form (content) template:
-
-  >>> zope.component.provideAdapter(tableFormFactory,
-  ...     (zope.interface.Interface, ITableFormLayer), IContentTemplate)
-
-Patch the request and call the form again:
-
-  >>> tableRequest = TestRequest()
-  >>> alsoProvides(tableRequest, ITableFormLayer)
-
-Now our new request should know the table based form template:
-
-  >>> addForm = PersonAddForm(root, tableRequest)
-  >>> print addForm()
-  <html>
-    <body>
-      <form action="http://127.0.0.1" method="post"
-        enctype="multipart/form-data" class="edit-form"
-        name="form" id="form">
-        <div class="viewspace">
-          <div class="required-info">
-            <span class="required">*</span>
-            &ndash; required
-          </div>
-          <div>
-          <table class="form-fields">
-                <tr class="row">
-                  <td class="label">
-                    <label for="form-widgets-name">
-                      <span>Name</span>
-                      <span class="required"> * </span>
-                    </label>
-                  </td>
-                  <td class="field">
-                    <div class="widget"><input type="text" id="form-widgets-name"
-                         name="form.widgets.name"
-                         class="text-widget required textline-field" value="" />
-                    </div>
-                  </td>
-                </tr>
-                <tr class="row">
-                  <td class="label">
-                    <label for="form-widgets-age">
-                      <span>Age</span>
-                    </label>
-                  </td>
-                  <td class="field">
-                    <div class="widget"><input type="text" id="form-widgets-age"
-                         name="form.widgets.age" class="text-widget int-field"
-                         value="20" />
-                    </div>
-                  </td>
-                </tr>
-          </table>
-        </div>
-      </div>
-      <div>
-        <div class="buttons">
-          <input type="submit" id="form-buttons-add"
-         name="form.buttons.add"
-         class="submit-widget button-field" value="Add" />
-        </div>
-      </div>
-      </form>
-    </body>
-  </html>
-
-
-`AddForm` rendering for `IAdding`
----------------------------------
-
-The `z3c.formui` package also provides a layout-aware version of
-`z3c.form.adding.AddForm` which can be used for creating forms for the
-`zope.app.container.interfaces.IAdding` mechanism.
-
-Let's check its template support. First, create the form for an `Adding`
-instance. We just need to define the ``create()`` method, because the default
-``add()`` and ``nextURL()`` methods are already defined using the `Adding`
-object.
-
-  >>> from z3c.formui import adding
-  >>> class AddingPersonAddForm(adding.AddForm):
-  ...
-  ...     fields = field.Fields(IPerson)
-  ...
-  ...     def create(self, data):
-  ...         return Person(**data)
-
-
-Let's now instantiate the adding component and isntantiate the add form:
-
-  >>> from zope.app.container.browser.adding import Adding
-  >>> rootAdding = Adding(root, divRequest)
-
-  >>> addForm = AddingPersonAddForm(rootAdding, divRequest)
-
-First, let's ensure that we can lookup a layout template for the form:
-
-  >>> layout = zope.component.getMultiAdapter(
-  ...     (addForm, divRequest), ILayoutTemplate)
-
-  >>> isinstance(layout, ptcompat.ViewPageTemplateFile)
-  True
-
-Okay, that worked. Let's now render the div-based addform:
-
-  >>> print addForm()
-  <html>
-    <body>
-      <form action="http://127.0.0.1" method="post"
-        enctype="multipart/form-data" class="edit-form"
-        name="form" id="form">
-        <div class="viewspace">
-          <div class="required-info">
-            <span class="required">*</span>
-            &ndash; required
-          </div>
-          <div>
-            <div id="form-widgets-name-row" class="row">
-              <div class="label">
-                <label for="form-widgets-name">
-                  <span>Name</span>
-                  <span class="required">*</span>
-                </label>
-              </div>
-              <div class="widget"><input type="text" id="form-widgets-name"
-                   name="form.widgets.name"
-                   class="text-widget required textline-field" value="" />
-              </div>
-            </div>
-            <div id="form-widgets-age-row" class="row">
-              <div class="label">
-                <label for="form-widgets-age">
-                  <span>Age</span>
-                </label>
-              </div>
-              <div class="widget"><input type="text" id="form-widgets-age"
-                   name="form.widgets.age" class="text-widget int-field"
-                   value="20" />
-              </div>
-            </div>
-          </div>
-        </div>
-        <div>
-          <div class="buttons">
-            <input type="submit" id="form-buttons-add"
-             name="form.buttons.add"
-             class="submit-widget button-field" value="Add" />
-          </div>
-        </div>
-      </form>
-    </body>
-  </html>
-
-Okay, now we are going to check table layout support.
-
-  >>> rootAdding = Adding(root, tableRequest)
-  >>> addForm = AddingPersonAddForm(rootAdding, tableRequest)
-
-Again, the layout should be available:
-
-  >>> layout = zope.component.getMultiAdapter((addForm, tableRequest),
-  ...     ILayoutTemplate)
-
-  >>> isinstance(layout, ptcompat.ViewPageTemplateFile)
-  True
-
-Let's now render the form:
-
-  >>> print addForm()
-  <html>
-    <body>
-      <form action="http://127.0.0.1" method="post"
-        enctype="multipart/form-data" class="edit-form"
-        name="form" id="form">
-        <div class="viewspace">
-          <div class="required-info">
-            <span class="required">*</span>
-            &ndash; required
-          </div>
-          <div>
-          <table class="form-fields">
-                <tr class="row">
-                  <td class="label">
-                    <label for="form-widgets-name">
-                      <span>Name</span>
-                      <span class="required"> * </span>
-                    </label>
-                  </td>
-                  <td class="field">
-                    <div class="widget"><input type="text" id="form-widgets-name"
-                         name="form.widgets.name"
-                         class="text-widget required textline-field" value="" />
-                    </div>
-                  </td>
-                </tr>
-                <tr class="row">
-                  <td class="label">
-                    <label for="form-widgets-age">
-                      <span>Age</span>
-                    </label>
-                  </td>
-                  <td class="field">
-                    <div class="widget"><input type="text" id="form-widgets-age"
-                         name="form.widgets.age" class="text-widget int-field"
-                         value="20" />
-                    </div>
-                  </td>
-                </tr>
-          </table>
-        </div>
-      </div>
-      <div>
-        <div class="buttons">
-          <input type="submit" id="form-buttons-add"
-         name="form.buttons.add"
-         class="submit-widget button-field" value="Add" />
-        </div>
-      </div>
-      </form>
-    </body>
-  </html>
-
-
-Form Macros
------------
-
-Load the configuration, which will make sure that all macros get registered
-correctly:
-
-  >>> from zope.configuration import xmlconfig
-  >>> import zope.component
-  >>> import zope.viewlet
-  >>> import zope.app.component
-  >>> import zope.app.publisher.browser
-  >>> import z3c.macro
-  >>> import z3c.template
-  >>> import z3c.formui
-  >>> xmlconfig.XMLConfig('meta.zcml', zope.component)()
-  >>> xmlconfig.XMLConfig('meta.zcml', zope.viewlet)()
-  >>> xmlconfig.XMLConfig('meta.zcml', zope.app.component)()
-  >>> xmlconfig.XMLConfig('meta.zcml', zope.app.publisher.browser)()
-  >>> xmlconfig.XMLConfig('meta.zcml', z3c.macro)()
-  >>> xmlconfig.XMLConfig('meta.zcml', z3c.template)()
-  >>> xmlconfig.XMLConfig('configure.zcml', z3c.formui)()
-
-Div IContentTemplate
---------------------
-
-Create some dummy form discriminators for calling div layout templates and
-macros and check the div IContentTemplates:
-
-  >>> objects = (addForm, divRequest)
-  >>> zope.component.getMultiAdapter(objects, IContentTemplate).filename
-  '...div-form.pt'
-
-  >>> objects = (form.DisplayForm(None, None), divRequest)
-  >>> zope.component.getMultiAdapter(objects, IContentTemplate, '').filename
-  '...div-form-display.pt'
-
-We offer the following named IContentTemplate:
-
-  >>> objects = (form.DisplayForm(None, None), divRequest)
-  >>> zope.component.getMultiAdapter(objects, IContentTemplate,
-  ...     'display').filename
-  '...div-form-display.pt'
-
-  >>> objects = (form.DisplayForm(None, None), divRequest)
-  >>> zope.component.getMultiAdapter(objects, IContentTemplate,
-  ...     'subform').filename
-  '...subform.pt'
-
-
-Table ILayoutTemplate
----------------------
-
-There is one generic layout template to build sub forms:
-
-  >>> objects = (form.DisplayForm(None, None), divRequest)
-  >>> zope.component.getMultiAdapter(objects, ILayoutTemplate,
-  ...     'subform').filename
-  '...subform-layout.pt'
-
-
-Div layout macros
------------------
-
-We have different form macros available for IInputForm:
-
-
-  >>> from z3c.macro.interfaces import IMacroTemplate
-  >>> objects = (None, addForm, divRequest)
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form')
-  [...div-form.pt'), ...metal:define-macro': u'form'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform')
-  [...div-form.pt'), ...define-macro': u'subform'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-label')
-  [...div-form.pt'), ...define-macro': u'label'...
-
-
-  >>> zope.component.getMultiAdapter(
-  ...     objects, IMacroTemplate, 'form-required-info')
-  [...div-form.pt'), ...define-macro', u'required-info'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-header')
-  [...div-form.pt'), ...define-macro': u'header'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-errors')
-  [...div-form.pt'), ...define-macro': u'errors'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'widget-rows')
-  [...div-form.pt'), ...define-macro': u'widget-rows'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'widget-row')
-  [...div-form.pt'), ...define-macro': u'widget-row'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-groups')
-  [...div-form.pt'), ...define-macro': u'groups'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-buttons')
-  [...div-form.pt'), ...define-macro', u'buttons'...
-
-
-And we have different form macros available for IDisplayForm:
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform-display')
-  [...div-form-display.pt'), ...define-macro': u'subform-display'...
-
-
-Table IContentTemplate
-----------------------
-
-Create some dummy form discriminators for calling table layout templates and
-macros and check the div IContentTemplates:
-
-  >>> objects = (addForm, tableRequest)
-  >>> zope.component.getMultiAdapter(objects, IContentTemplate, '').filename
-  '...table-form.pt'
-
-  >>> objects = (form.DisplayForm(None, None), tableRequest)
-  >>> zope.component.getMultiAdapter(objects, IContentTemplate, '').filename
-  '...table-form-display.pt'
-
-We offer the following named IContentTemplate:
-
-  >>> objects = (form.DisplayForm(None, None), tableRequest)
-  >>> zope.component.getMultiAdapter(objects, IContentTemplate,
-  ...     'display').filename
-  '...table-form-display.pt'
-
-  >>> objects = (form.DisplayForm(None, None), tableRequest)
-  >>> zope.component.getMultiAdapter(objects, IContentTemplate,
-  ...     'subform').filename
-  '...subform.pt'
-
-
-
-Table ILayoutTemplate
----------------------
-
-There is one generic layout template to build sub forms:
-
-  >>> objects = (form.DisplayForm(None, None), tableRequest)
-  >>> zope.component.getMultiAdapter(objects, ILayoutTemplate,
-  ...     'subform').filename
-  '...subform-layout.pt'
-
-
-Table layout macros
--------------------
-
-We have different form macros available for IInputForm:
-
-  >>> objects = (None, addForm, tableRequest)
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form')
-  [...table-form.pt'), ...metal:define-macro': u'form'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform')
-  [...table-form.pt'), ...define-macro': u'subform'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-label')
-  [...table-form.pt'), ...define-macro': u'label'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-required-info')
-  [...table-form.pt'), ...define-macro', u'required-info'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-header')
-  [...table-form.pt'), ...define-macro': u'header'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-errors')
-  [...table-form.pt'), ...define-macro': u'errors'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-table')
-  [...table-form.pt'), ...define-macro', u'formtable'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-row')
-  [...table-form.pt'), ...define-macro': u'formrow'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-label-cell')
-  [...table-form.pt'), ...define-macro', u'labelcell'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-widget-cell')
-  [...table-form.pt'), ...define-macro', u'widgetcell'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-groups')
-  [...table-form.pt'), ...define-macro': u'groups'...
-
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-buttons')
-  [...table-form.pt'), ...define-macro', u'buttons'...
-
-
-And we have different form macros available for IDisplayForm:
-
-  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform-display')
-  [...table-form-display.pt'), ...define-macro': u'subform-display'...
-
-
-Subform
--------
-
-Let's give a quick overview how subform content and layout templates get used:
-First define a new form which uses the template getter methods offered
-from z3.template
-
-  >>> from z3c.template.template import getPageTemplate
-  >>> from z3c.template.template import getLayoutTemplate
-
-The ``provider`` TALES expression which is a part of the lookup concept
-was already registered by the testing setup, so we don't need to do it
-here.
-
-and the TALES expression called ``macro`` which can lookup our macro adapters.
-Yes, macros are adapters in our content/layout template concept. See z3c.macro
-for more information about the implementation. However, we already registered
-the ``macro`` type in the testing setup, as it's needed for rendering form
-templates.
-
-and at least we need a pagelet
-renderer. By default we use the provider called ``PageletRenderer`` defined
-in the z3c.pagelet package. But right now, we don't have a dependency on
-this package. So let's implement a simple renderer and use them as a
-IContentProvider:
-
-  >>> class PageletRenderer(object):
-  ...     zope.component.adapts(zope.interface.Interface,
-  ...         zope.publisher.interfaces.browser.IBrowserRequest,
-  ...         zope.interface.Interface)
-  ...
-  ...     def __init__(self, context, request, pagelet):
-  ...         self.__updated = False
-  ...         self.__parent__ = pagelet
-  ...         self.context = context
-  ...         self.request = request
-  ...
-  ...     def update(self):
-  ...         pass
-  ...
-  ...     def render(self):
-  ...         return self.__parent__.render()
-
-  >>> from zope.contentprovider.interfaces import IContentProvider
-  >>> zope.component.provideAdapter(PageletRenderer,
-  ...     provides=IContentProvider, name='pagelet')
-
-Now define the form:
-
-  >>> class PersonEditForm(form.EditForm):
-  ...     """Edit form including layout support. See z3c.formui.form."""
-  ...
-  ...     template = getPageTemplate('subform')
-  ...     layout = getLayoutTemplate('subform')
-  ...
-  ...     fields = field.Fields(IPerson)
-
-Now we can render the form with our previous created person instance:
-
-  >>> person = Person(u'Jessy', 6)
-  >>> editForm = PersonEditForm(person, divRequest)
-
-Now we call the form which will update and render it:
-
-  >>> print editForm()
-  <div class="viewspace">
-    <div class="required-info">
-      <span class="required">*</span>
-      &ndash; required
-    </div>
-    <div>
-      <div id="form-widgets-name-row" class="row">
-        <div class="label">
-          <label for="form-widgets-name">
-            <span>Name</span>
-            <span class="required">*</span>
-          </label>
-        </div>
-        <div class="widget"><input type="text" id="form-widgets-name"
-             name="form.widgets.name"
-             class="text-widget required textline-field"
-             value="Jessy" />
-        </div>
-      </div>
-      <div id="form-widgets-age-row" class="row">
-        <div class="label">
-          <label for="form-widgets-age">
-            <span>Age</span>
-          </label>
-        </div>
-        <div class="widget"><input type="text" id="form-widgets-age"
-           name="form.widgets.age" class="text-widget int-field"
-           value="6" />
-        </div>
-      </div>
-    </div>
-  </div>
-  <div>
-    <div class="buttons">
-      <input type="submit" id="form-buttons-apply"
-             name="form.buttons.apply"
-             class="submit-widget button-field" value="Apply" />
-    </div>
-  </div>
-
-You can see that the form above is a real subform. It doesn't define the form
-tag which makes it usable as a subform in parent forms.
-
-Of course this works with table layout based forms too. Let's use our table
-request and render the form again:
-
-  >>> editForm = PersonEditForm(person, tableRequest)
-  >>> print editForm()
-  <div class="viewspace">
-    <div class="required-info">
-      <span class="required">*</span>
-      &ndash; required
-    </div>
-    <div>
-      <table class="form-fields">
-        <tr class="row">
-          <td class="label">
-            <label for="form-widgets-name">
-              <span>Name</span>
-              <span class="required"> * </span>
-            </label>
-          </td>
-          <td class="field">
-            <div class="widget"><input type="text" id="form-widgets-name"
-                 name="form.widgets.name"
-                 class="text-widget required textline-field"
-                 value="Jessy" />
-            </div>
-          </td>
-        </tr>
-        <tr class="row">
-          <td class="label">
-            <label for="form-widgets-age">
-              <span>Age</span>
-            </label>
-          </td>
-          <td class="field">
-            <div class="widget"><input type="text" id="form-widgets-age"
-                 name="form.widgets.age" class="text-widget int-field"
-                 value="6" />
-            </div>
-          </td>
-        </tr>
-      </table>
-    </div>
-  </div>
-  <div>
-    <div class="buttons">
-      <input type="submit" id="form-buttons-apply"
-             name="form.buttons.apply"
-            class="submit-widget button-field" value="Apply" />
-    </div>
-  </div>
-
-Redirection
------------
-
-The form doesn't bother rendering itself and its layout when
-request is a redirection as the rendering doesn't make any sense with
-browser requests in that case. Let's create a view that does a
-redirection in its update method:
-
- >>> class RedirectingView(PersonEditForm):
- ...     def update(self):
- ...         super(RedirectingView, self).update()
- ...         self.request.response.redirect('http://www.google.com/')
-
-It will return an empty string when called as a browser page.
-
- >>> redirectView = RedirectingView(person, divRequest)
- >>> redirectView() == ''
- True
-
-However, the ``render`` method will render form's template as usual:
-
- >>> '<div class="viewspace">' in redirectView.render()
- True
-
-The same thing should work for AddForms:
-
- >>> class RedirectingAddView(PersonAddForm):
- ...     def update(self):
- ...         super(RedirectingAddView, self).update()
- ...         self.request.response.redirect('http://www.google.com/')
- >>> redirectView = RedirectingAddView(person, divRequest)
- >>> redirectView() == ''
- True
-
-No required fields
-------------------
-
-If there no required fields in the form, standard templates won't render
-the "required-info" hint.
-
-  >>> class IAdditionalInfo(zope.interface.Interface):
-  ...
-  ...     location = zope.schema.TextLine(title=u'Location', required=False)
-  ...     about = zope.schema.Text(title=u'About', required=False)  
-
-  >>> class AdditionalInfoForm(form.AddForm):
-  ...
-  ...     fields = field.Fields(IAdditionalInfo)
-  
-  >>> additionalInfoForm = AdditionalInfoForm(root, divRequest)
-  >>> additionalInfoForm.update()
-  >>> '<div class="required-info">' in additionalInfoForm.render()
-  False
-
-  >>> additionalInfoForm = AdditionalInfoForm(root, tableRequest)
-  >>> additionalInfoForm.update()
-  >>> '<div class="required-info">' in additionalInfoForm.render()
-  False
-
-Cleanup
--------
-
-  >>> import shutil
-  >>> shutil.rmtree(temp_dir)

Copied: z3c.formui/tags/2.1.0/src/z3c/formui/README.txt (from rev 103464, z3c.formui/trunk/src/z3c/formui/README.txt)
===================================================================
--- z3c.formui/tags/2.1.0/src/z3c/formui/README.txt	                        (rev 0)
+++ z3c.formui/tags/2.1.0/src/z3c/formui/README.txt	2009-09-01 18:23:39 UTC (rev 103465)
@@ -0,0 +1,909 @@
+====================
+Form User Interfaces
+====================
+
+This package provides several useful templates to get a quick start with the
+``z3c.form`` package. Previous form frameworks always included default
+templates that were implemented in a particular user-interface development
+pattern. If you wanted to use an alternative strategy to develop user
+interfaces, it was often tedious to do so. This package aims to provide some
+options without requiring them for the basic framework.
+
+
+Layout Template Support
+-----------------------
+
+One common pattern in Zope 3 user interface development is the use of layout
+templates (see z3c.template). This package provides some mixin classes to the
+regular form classes to support layout-based templating.
+
+  >>> from z3c.form import testing
+  >>> testing.setupFormDefaults()
+
+Before we can start writing forms, we must have the content to work with:
+
+  >>> import zope.interface
+  >>> import zope.schema
+  >>> class IPerson(zope.interface.Interface):
+  ...
+  ...     name = zope.schema.TextLine(
+  ...         title=u'Name',
+  ...         required=True)
+  ...
+  ...     age = zope.schema.Int(
+  ...         title=u'Age',
+  ...         description=u"The person's age.",
+  ...         min=0,
+  ...         default=20,
+  ...         required=False)
+
+  >>> from zope.schema.fieldproperty import FieldProperty
+  >>> class Person(object):
+  ...     zope.interface.implements(IPerson)
+  ...
+  ...     name = FieldProperty(IPerson['name'])
+  ...     age = FieldProperty(IPerson['age'])
+  ...
+  ...     def __init__(self, name, age):
+  ...         self.name = name
+  ...         self.age = age
+  ...
+  ...     def __repr__(self):
+  ...         return '<%s %r>' % (self.__class__.__name__, self.name)
+
+Okay, that should suffice for now. Let's now create a working add form:
+
+  >>> from z3c.form import field
+  >>> from z3c.formui import form, layout
+  >>> class PersonAddForm(form.AddForm):
+  ...
+  ...     fields = field.Fields(IPerson)
+  ...
+  ...     def create(self, data):
+  ...         return Person(**data)
+  ...
+  ...     def add(self, object):
+  ...         self.context[object.id] = object
+  ...
+  ...     def nextURL(self):
+  ...         return 'index.html'
+
+Let's create a request:
+
+  >>> from z3c.form.testing import TestRequest
+  >>> from zope.interface import alsoProvides
+  >>> divRequest = TestRequest()
+
+And support the div form layer for our request:
+
+  >>> from z3c.formui.interfaces import IDivFormLayer
+  >>> alsoProvides(divRequest, IDivFormLayer)
+
+Now create the form:
+
+  >>> addForm = PersonAddForm(root, divRequest)
+
+Since we have not specified a template yet, we have to do this now. We use our
+div based form template:
+
+  >>> import os
+  >>> import z3c.formui
+  >>> divFormTemplate = os.path.join(os.path.dirname(z3c.formui.__file__),
+  ...     'div-form.pt')
+
+  >>> from z3c.template.template import TemplateFactory
+  >>> divFormFactory = TemplateFactory(divFormTemplate, 'text/html')
+
+Now register the form (content) template:
+
+  >>> import zope.interface
+  >>> import zope.component
+  >>> from z3c.template.interfaces import IContentTemplate
+  >>> zope.component.provideAdapter(divFormFactory,
+  ...     (zope.interface.Interface, IDivFormLayer),
+  ...     IContentTemplate)
+
+And let's define a layout template which simply calls the render method. For a
+more advanced content/layout render concept see z3c.pagelet.
+
+  >>> import tempfile
+  >>> temp_dir = tempfile.mkdtemp()
+
+  >>> myLayout = os.path.join(temp_dir, 'myLayout.pt')
+  >>> open(myLayout, 'w').write('''<html>
+  ...   <body>
+  ...     <tal:block content="structure view/render">
+  ...       content
+  ...     </tal:block>
+  ...   </body>
+  ... </html>''')
+  >>> myLayoutFactory = TemplateFactory(myLayout, 'text/html')
+
+  >>> from z3c.template.interfaces import ILayoutTemplate
+  >>> zope.component.provideAdapter(myLayoutFactory,
+  ...     (zope.interface.Interface, zope.interface.Interface), ILayoutTemplate)
+
+Now we can get our layout template:
+
+  >>> layout = zope.component.getMultiAdapter((addForm, divRequest),
+  ...     ILayoutTemplate)
+
+  >>> from z3c import ptcompat
+  >>> isinstance(layout, ptcompat.ViewPageTemplateFile)
+  True
+
+
+DIV-based Layout
+----------------
+
+Let's now render the page. Note the output doesn't contain the layout template:
+
+  >>> addForm.update()
+  >>> print addForm.render()
+  <form action="http://127.0.0.1" method="post"
+          enctype="multipart/form-data" class="edit-form"
+          name="form" id="form">
+    <div class="viewspace">
+      <div class="required-info">
+        <span class="required">*</span> &ndash; required
+      </div>
+      <div>
+        <div id="form-widgets-name-row" class="row">
+          <div class="label">
+            <label for="form-widgets-name">
+              <span>Name</span>
+              <span class="required">*</span>
+            </label>
+          </div>
+          <div class="widget"><input type="text" id="form-widgets-name"
+                   name="form.widgets.name"
+                   class="text-widget required textline-field" value="" />
+          </div>
+        </div>
+        <div id="form-widgets-age-row" class="row">
+          <div class="label">
+            <label for="form-widgets-age">
+              <span>Age</span>
+            </label>
+          </div>
+          <div class="widget"><input type="text" id="form-widgets-age"
+                   name="form.widgets.age" class="text-widget int-field"
+                   value="20" />
+          </div>
+        </div>
+      </div>
+    </div>
+    <div>
+      <div class="buttons">
+        <input type="submit" id="form-buttons-add"
+               name="form.buttons.add"
+               class="submit-widget button-field" value="Add" />
+      </div>
+    </div>
+  </form>
+
+But we can call our form which uses the new layout template which renders
+the form within the div-form content template:
+
+  >>> print addForm()
+  <html>
+    <body>
+      <form action="http://127.0.0.1" method="post"
+        enctype="multipart/form-data" class="edit-form"
+        name="form" id="form">
+        <div class="viewspace">
+          <div class="required-info">
+            <span class="required">*</span>
+            &ndash; required
+          </div>
+          <div>
+            <div id="form-widgets-name-row" class="row">
+              <div class="label">
+                <label for="form-widgets-name">
+                  <span>Name</span>
+                  <span class="required">*</span>
+                </label>
+              </div>
+              <div class="widget"><input type="text" id="form-widgets-name"
+                   name="form.widgets.name"
+                   class="text-widget required textline-field" value="" />
+              </div>
+            </div>
+            <div id="form-widgets-age-row" class="row">
+              <div class="label">
+                <label for="form-widgets-age">
+                  <span>Age</span>
+                </label>
+              </div>
+              <div class="widget"><input type="text" id="form-widgets-age"
+                   name="form.widgets.age" class="text-widget int-field"
+                   value="20" />
+              </div>
+            </div>
+          </div>
+        </div>
+        <div>
+          <div class="buttons">
+            <input type="submit" id="form-buttons-add"
+             name="form.buttons.add"
+             class="submit-widget button-field" value="Add" />
+          </div>
+        </div>
+      </form>
+    </body>
+  </html>
+
+
+Table-based Forms
+-----------------
+
+There is a table based layout too. Let's define the template and use them:
+
+  >>> from z3c.formui.interfaces import ITableFormLayer
+  >>> tableFormTemplate = os.path.join(os.path.dirname(z3c.formui.__file__),
+  ...     'table-form.pt')
+
+  >>> from z3c.template.template import TemplateFactory
+  >>> tableFormFactory = TemplateFactory(tableFormTemplate, 'text/html')
+
+Now register the form (content) template:
+
+  >>> zope.component.provideAdapter(tableFormFactory,
+  ...     (zope.interface.Interface, ITableFormLayer), IContentTemplate)
+
+Patch the request and call the form again:
+
+  >>> tableRequest = TestRequest()
+  >>> alsoProvides(tableRequest, ITableFormLayer)
+
+Now our new request should know the table based form template:
+
+  >>> addForm = PersonAddForm(root, tableRequest)
+  >>> print addForm()
+  <html>
+    <body>
+      <form action="http://127.0.0.1" method="post"
+        enctype="multipart/form-data" class="edit-form"
+        name="form" id="form">
+        <div class="viewspace">
+          <div class="required-info">
+            <span class="required">*</span>
+            &ndash; required
+          </div>
+          <div>
+          <table class="form-fields">
+                <tr class="row">
+                  <td class="label">
+                    <label for="form-widgets-name">
+                      <span>Name</span>
+                      <span class="required"> * </span>
+                    </label>
+                  </td>
+                  <td class="field">
+                    <div class="widget"><input type="text" id="form-widgets-name"
+                         name="form.widgets.name"
+                         class="text-widget required textline-field" value="" />
+                    </div>
+                  </td>
+                </tr>
+                <tr class="row">
+                  <td class="label">
+                    <label for="form-widgets-age">
+                      <span>Age</span>
+                    </label>
+                  </td>
+                  <td class="field">
+                    <div class="widget"><input type="text" id="form-widgets-age"
+                         name="form.widgets.age" class="text-widget int-field"
+                         value="20" />
+                    </div>
+                  </td>
+                </tr>
+          </table>
+        </div>
+      </div>
+      <div>
+        <div class="buttons">
+          <input type="submit" id="form-buttons-add"
+         name="form.buttons.add"
+         class="submit-widget button-field" value="Add" />
+        </div>
+      </div>
+      </form>
+    </body>
+  </html>
+
+
+`AddForm` rendering for `IAdding`
+---------------------------------
+
+The `z3c.formui` package also provides a layout-aware version of
+`z3c.form.adding.AddForm` which can be used for creating forms for the
+`zope.app.container.interfaces.IAdding` mechanism.
+
+Let's check its template support. First, create the form for an `Adding`
+instance. We just need to define the ``create()`` method, because the default
+``add()`` and ``nextURL()`` methods are already defined using the `Adding`
+object.
+
+  >>> from z3c.formui import adding
+  >>> class AddingPersonAddForm(adding.AddForm):
+  ...
+  ...     fields = field.Fields(IPerson)
+  ...
+  ...     def create(self, data):
+  ...         return Person(**data)
+
+
+Let's now instantiate the adding component and isntantiate the add form:
+
+  >>> from zope.app.container.browser.adding import Adding
+  >>> rootAdding = Adding(root, divRequest)
+
+  >>> addForm = AddingPersonAddForm(rootAdding, divRequest)
+
+First, let's ensure that we can lookup a layout template for the form:
+
+  >>> layout = zope.component.getMultiAdapter(
+  ...     (addForm, divRequest), ILayoutTemplate)
+
+  >>> isinstance(layout, ptcompat.ViewPageTemplateFile)
+  True
+
+Okay, that worked. Let's now render the div-based addform:
+
+  >>> print addForm()
+  <html>
+    <body>
+      <form action="http://127.0.0.1" method="post"
+        enctype="multipart/form-data" class="edit-form"
+        name="form" id="form">
+        <div class="viewspace">
+          <div class="required-info">
+            <span class="required">*</span>
+            &ndash; required
+          </div>
+          <div>
+            <div id="form-widgets-name-row" class="row">
+              <div class="label">
+                <label for="form-widgets-name">
+                  <span>Name</span>
+                  <span class="required">*</span>
+                </label>
+              </div>
+              <div class="widget"><input type="text" id="form-widgets-name"
+                   name="form.widgets.name"
+                   class="text-widget required textline-field" value="" />
+              </div>
+            </div>
+            <div id="form-widgets-age-row" class="row">
+              <div class="label">
+                <label for="form-widgets-age">
+                  <span>Age</span>
+                </label>
+              </div>
+              <div class="widget"><input type="text" id="form-widgets-age"
+                   name="form.widgets.age" class="text-widget int-field"
+                   value="20" />
+              </div>
+            </div>
+          </div>
+        </div>
+        <div>
+          <div class="buttons">
+            <input type="submit" id="form-buttons-add"
+             name="form.buttons.add"
+             class="submit-widget button-field" value="Add" />
+          </div>
+        </div>
+      </form>
+    </body>
+  </html>
+
+Okay, now we are going to check table layout support.
+
+  >>> rootAdding = Adding(root, tableRequest)
+  >>> addForm = AddingPersonAddForm(rootAdding, tableRequest)
+
+Again, the layout should be available:
+
+  >>> layout = zope.component.getMultiAdapter((addForm, tableRequest),
+  ...     ILayoutTemplate)
+
+  >>> isinstance(layout, ptcompat.ViewPageTemplateFile)
+  True
+
+Let's now render the form:
+
+  >>> print addForm()
+  <html>
+    <body>
+      <form action="http://127.0.0.1" method="post"
+        enctype="multipart/form-data" class="edit-form"
+        name="form" id="form">
+        <div class="viewspace">
+          <div class="required-info">
+            <span class="required">*</span>
+            &ndash; required
+          </div>
+          <div>
+          <table class="form-fields">
+                <tr class="row">
+                  <td class="label">
+                    <label for="form-widgets-name">
+                      <span>Name</span>
+                      <span class="required"> * </span>
+                    </label>
+                  </td>
+                  <td class="field">
+                    <div class="widget"><input type="text" id="form-widgets-name"
+                         name="form.widgets.name"
+                         class="text-widget required textline-field" value="" />
+                    </div>
+                  </td>
+                </tr>
+                <tr class="row">
+                  <td class="label">
+                    <label for="form-widgets-age">
+                      <span>Age</span>
+                    </label>
+                  </td>
+                  <td class="field">
+                    <div class="widget"><input type="text" id="form-widgets-age"
+                         name="form.widgets.age" class="text-widget int-field"
+                         value="20" />
+                    </div>
+                  </td>
+                </tr>
+          </table>
+        </div>
+      </div>
+      <div>
+        <div class="buttons">
+          <input type="submit" id="form-buttons-add"
+         name="form.buttons.add"
+         class="submit-widget button-field" value="Add" />
+        </div>
+      </div>
+      </form>
+    </body>
+  </html>
+
+
+Form Macros
+-----------
+
+Load the configuration, which will make sure that all macros get registered
+correctly:
+
+  >>> from zope.configuration import xmlconfig
+  >>> import zope.component
+  >>> import zope.viewlet
+  >>> import zope.app.component
+  >>> import zope.app.publisher.browser
+  >>> import z3c.macro
+  >>> import z3c.template
+  >>> import z3c.formui
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.component)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.viewlet)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.app.component)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.app.publisher.browser)()
+  >>> xmlconfig.XMLConfig('meta.zcml', z3c.macro)()
+  >>> xmlconfig.XMLConfig('meta.zcml', z3c.template)()
+  >>> xmlconfig.XMLConfig('configure.zcml', z3c.formui)()
+
+Div IContentTemplate
+--------------------
+
+Create some dummy form discriminators for calling div layout templates and
+macros and check the div IContentTemplates:
+
+  >>> objects = (addForm, divRequest)
+  >>> zope.component.getMultiAdapter(objects, IContentTemplate).filename
+  '...div-form.pt'
+
+  >>> objects = (form.DisplayForm(None, None), divRequest)
+  >>> zope.component.getMultiAdapter(objects, IContentTemplate, '').filename
+  '...div-form-display.pt'
+
+We offer the following named IContentTemplate:
+
+  >>> objects = (form.DisplayForm(None, None), divRequest)
+  >>> zope.component.getMultiAdapter(objects, IContentTemplate,
+  ...     'display').filename
+  '...div-form-display.pt'
+
+  >>> objects = (form.DisplayForm(None, None), divRequest)
+  >>> zope.component.getMultiAdapter(objects, IContentTemplate,
+  ...     'subform').filename
+  '...subform.pt'
+
+
+Table ILayoutTemplate
+---------------------
+
+There is one generic layout template to build sub forms:
+
+  >>> objects = (form.DisplayForm(None, None), divRequest)
+  >>> zope.component.getMultiAdapter(objects, ILayoutTemplate,
+  ...     'subform').filename
+  '...subform-layout.pt'
+
+
+Div layout macros
+-----------------
+
+We have different form macros available for IInputForm:
+
+
+  >>> from z3c.macro.interfaces import IMacroTemplate
+  >>> objects = (None, addForm, divRequest)
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form')
+  [...div-form.pt'), ...metal:define-macro': u'form'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform')
+  [...div-form.pt'), ...define-macro': u'subform'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-label')
+  [...div-form.pt'), ...define-macro': u'label'...
+
+
+  >>> zope.component.getMultiAdapter(
+  ...     objects, IMacroTemplate, 'form-required-info')
+  [...div-form.pt'), ...define-macro', u'required-info'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-header')
+  [...div-form.pt'), ...define-macro': u'header'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-errors')
+  [...div-form.pt'), ...define-macro': u'errors'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'widget-rows')
+  [...div-form.pt'), ...define-macro': u'widget-rows'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'widget-row')
+  [...div-form.pt'), ...define-macro': u'widget-row'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-groups')
+  [...div-form.pt'), ...define-macro': u'groups'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-buttons')
+  [...div-form.pt'), ...define-macro', u'buttons'...
+
+
+And we have different form macros available for IDisplayForm:
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform-display')
+  [...div-form-display.pt'), ...define-macro': u'subform-display'...
+
+
+Table IContentTemplate
+----------------------
+
+Create some dummy form discriminators for calling table layout templates and
+macros and check the div IContentTemplates:
+
+  >>> objects = (addForm, tableRequest)
+  >>> zope.component.getMultiAdapter(objects, IContentTemplate, '').filename
+  '...table-form.pt'
+
+  >>> objects = (form.DisplayForm(None, None), tableRequest)
+  >>> zope.component.getMultiAdapter(objects, IContentTemplate, '').filename
+  '...table-form-display.pt'
+
+We offer the following named IContentTemplate:
+
+  >>> objects = (form.DisplayForm(None, None), tableRequest)
+  >>> zope.component.getMultiAdapter(objects, IContentTemplate,
+  ...     'display').filename
+  '...table-form-display.pt'
+
+  >>> objects = (form.DisplayForm(None, None), tableRequest)
+  >>> zope.component.getMultiAdapter(objects, IContentTemplate,
+  ...     'subform').filename
+  '...subform.pt'
+
+
+
+Table ILayoutTemplate
+---------------------
+
+There is one generic layout template to build sub forms:
+
+  >>> objects = (form.DisplayForm(None, None), tableRequest)
+  >>> zope.component.getMultiAdapter(objects, ILayoutTemplate,
+  ...     'subform').filename
+  '...subform-layout.pt'
+
+
+Table layout macros
+-------------------
+
+We have different form macros available for IInputForm:
+
+  >>> objects = (None, addForm, tableRequest)
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form')
+  [...table-form.pt'), ...metal:define-macro': u'form'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform')
+  [...table-form.pt'), ...define-macro': u'subform'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-label')
+  [...table-form.pt'), ...define-macro': u'label'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-required-info')
+  [...table-form.pt'), ...define-macro', u'required-info'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-header')
+  [...table-form.pt'), ...define-macro': u'header'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-errors')
+  [...table-form.pt'), ...define-macro': u'errors'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-table')
+  [...table-form.pt'), ...define-macro', u'formtable'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-row')
+  [...table-form.pt'), ...define-macro': u'formrow'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-label-cell')
+  [...table-form.pt'), ...define-macro', u'labelcell'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-widget-cell')
+  [...table-form.pt'), ...define-macro', u'widgetcell'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-groups')
+  [...table-form.pt'), ...define-macro': u'groups'...
+
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'form-buttons')
+  [...table-form.pt'), ...define-macro', u'buttons'...
+
+
+And we have different form macros available for IDisplayForm:
+
+  >>> zope.component.getMultiAdapter(objects, IMacroTemplate, 'subform-display')
+  [...table-form-display.pt'), ...define-macro': u'subform-display'...
+
+
+Subform
+-------
+
+Let's give a quick overview how subform content and layout templates get used:
+First define a new form which uses the template getter methods offered
+from z3.template
+
+  >>> from z3c.template.template import getPageTemplate
+  >>> from z3c.template.template import getLayoutTemplate
+
+The ``provider`` TALES expression which is a part of the lookup concept
+was already registered by the testing setup, so we don't need to do it
+here.
+
+and the TALES expression called ``macro`` which can lookup our macro adapters.
+Yes, macros are adapters in our content/layout template concept. See z3c.macro
+for more information about the implementation. However, we already registered
+the ``macro`` type in the testing setup, as it's needed for rendering form
+templates.
+
+and at least we need a pagelet
+renderer. By default we use the provider called ``PageletRenderer`` defined
+in the z3c.pagelet package. But right now, we don't have a dependency on
+this package. So let's implement a simple renderer and use them as a
+IContentProvider:
+
+  >>> class PageletRenderer(object):
+  ...     zope.component.adapts(zope.interface.Interface,
+  ...         zope.publisher.interfaces.browser.IBrowserRequest,
+  ...         zope.interface.Interface)
+  ...
+  ...     def __init__(self, context, request, pagelet):
+  ...         self.__updated = False
+  ...         self.__parent__ = pagelet
+  ...         self.context = context
+  ...         self.request = request
+  ...
+  ...     def update(self):
+  ...         pass
+  ...
+  ...     def render(self):
+  ...         return self.__parent__.render()
+
+  >>> from zope.contentprovider.interfaces import IContentProvider
+  >>> zope.component.provideAdapter(PageletRenderer,
+  ...     provides=IContentProvider, name='pagelet')
+
+Now define the form:
+
+  >>> class PersonEditForm(form.EditForm):
+  ...     """Edit form including layout support. See z3c.formui.form."""
+  ...
+  ...     template = getPageTemplate('subform')
+  ...     layout = getLayoutTemplate('subform')
+  ...
+  ...     fields = field.Fields(IPerson)
+
+Now we can render the form with our previous created person instance:
+
+  >>> person = Person(u'Jessy', 6)
+  >>> editForm = PersonEditForm(person, divRequest)
+
+Now we call the form which will update and render it:
+
+  >>> print editForm()
+  <div class="viewspace">
+    <div class="required-info">
+      <span class="required">*</span>
+      &ndash; required
+    </div>
+    <div>
+      <div id="form-widgets-name-row" class="row">
+        <div class="label">
+          <label for="form-widgets-name">
+            <span>Name</span>
+            <span class="required">*</span>
+          </label>
+        </div>
+        <div class="widget"><input type="text" id="form-widgets-name"
+             name="form.widgets.name"
+             class="text-widget required textline-field"
+             value="Jessy" />
+        </div>
+      </div>
+      <div id="form-widgets-age-row" class="row">
+        <div class="label">
+          <label for="form-widgets-age">
+            <span>Age</span>
+          </label>
+        </div>
+        <div class="widget"><input type="text" id="form-widgets-age"
+           name="form.widgets.age" class="text-widget int-field"
+           value="6" />
+        </div>
+      </div>
+    </div>
+  </div>
+  <div>
+    <div class="buttons">
+      <input type="submit" id="form-buttons-apply"
+             name="form.buttons.apply"
+             class="submit-widget button-field" value="Apply" />
+    </div>
+  </div>
+
+You can see that the form above is a real subform. It doesn't define the form
+tag which makes it usable as a subform in parent forms.
+
+Of course this works with table layout based forms too. Let's use our table
+request and render the form again:
+
+  >>> editForm = PersonEditForm(person, tableRequest)
+  >>> print editForm()
+  <div class="viewspace">
+    <div class="required-info">
+      <span class="required">*</span>
+      &ndash; required
+    </div>
+    <div>
+      <table class="form-fields">
+        <tr class="row">
+          <td class="label">
+            <label for="form-widgets-name">
+              <span>Name</span>
+              <span class="required"> * </span>
+            </label>
+          </td>
+          <td class="field">
+            <div class="widget"><input type="text" id="form-widgets-name"
+                 name="form.widgets.name"
+                 class="text-widget required textline-field"
+                 value="Jessy" />
+            </div>
+          </td>
+        </tr>
+        <tr class="row">
+          <td class="label">
+            <label for="form-widgets-age">
+              <span>Age</span>
+            </label>
+          </td>
+          <td class="field">
+            <div class="widget"><input type="text" id="form-widgets-age"
+                 name="form.widgets.age" class="text-widget int-field"
+                 value="6" />
+            </div>
+          </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+  <div>
+    <div class="buttons">
+      <input type="submit" id="form-buttons-apply"
+             name="form.buttons.apply"
+            class="submit-widget button-field" value="Apply" />
+    </div>
+  </div>
+
+Redirection
+-----------
+
+The form doesn't bother rendering itself and its layout when
+request is a redirection as the rendering doesn't make any sense with
+browser requests in that case. Let's create a view that does a
+redirection in its update method:
+
+ >>> class RedirectingView(PersonEditForm):
+ ...     def update(self):
+ ...         super(RedirectingView, self).update()
+ ...         self.request.response.redirect('.')
+
+It will return an empty string when called as a browser page.
+
+ >>> redirectView = RedirectingView(person, divRequest)
+ >>> redirectView() == ''
+ True
+
+However, the ``render`` method will render form's template as usual:
+
+ >>> '<div class="viewspace">' in redirectView.render()
+ True
+
+The same thing should work for AddForms:
+
+ >>> class RedirectingAddView(PersonAddForm):
+ ...     def update(self):
+ ...         super(RedirectingAddView, self).update()
+ ...         self.request.response.redirect('.')
+ >>> redirectView = RedirectingAddView(person, divRequest)
+ >>> redirectView() == ''
+ True
+
+No required fields
+------------------
+
+If there no required fields in the form, standard templates won't render
+the "required-info" hint.
+
+  >>> class IAdditionalInfo(zope.interface.Interface):
+  ...
+  ...     location = zope.schema.TextLine(title=u'Location', required=False)
+  ...     about = zope.schema.Text(title=u'About', required=False)  
+
+  >>> class AdditionalInfoForm(form.AddForm):
+  ...
+  ...     fields = field.Fields(IAdditionalInfo)
+  
+  >>> additionalInfoForm = AdditionalInfoForm(root, divRequest)
+  >>> additionalInfoForm.update()
+  >>> '<div class="required-info">' in additionalInfoForm.render()
+  False
+
+  >>> additionalInfoForm = AdditionalInfoForm(root, tableRequest)
+  >>> additionalInfoForm.update()
+  >>> '<div class="required-info">' in additionalInfoForm.render()
+  False
+
+Cleanup
+-------
+
+  >>> import shutil
+  >>> shutil.rmtree(temp_dir)



More information about the checkins mailing list