[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/Forms/Browser - EditView.py:1.1 __init__.py:1.2 edit.pt:1.1 meta.zcml:1.1

Jim Fulton jim@zope.com
Mon, 11 Nov 2002 15:29:59 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/App/Forms/Browser
In directory cvs.zope.org:/tmp/cvs-serv16646

Added Files:
	EditView.py __init__.py edit.pt meta.zcml 
Log Message:
Added a mechanism for customizable automatic editing views. Views
are generated from a schema and can be customized with a class or an
alternate template.


=== Added File Zope3/lib/python/Zope/App/Forms/Browser/EditView.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""
$Id: EditView.py,v 1.1 2002/11/11 20:29:58 jim Exp $
"""

from datetime import datetime
from Zope.Publisher.Browser.BrowserView import BrowserView
from Zope.App.Forms.Views.Browser import Widget
from Zope.App.Forms.Exceptions import WidgetsError
from Zope.App.Forms.Utility import setUpEditWidgets, getWidgetsData
from Zope.App.Forms.Utility import haveWidgetsData, fieldNames
from Zope.Configuration.Action import Action
from Zope.App.PageTemplate.ViewPageTemplateFile import ViewPageTemplateFile
from Zope.Security.Checker import defineChecker, NamesChecker
from Zope.ComponentArchitecture.GlobalViewService import provideView
from Zope.Publisher.Browser.IBrowserPresentation import IBrowserPresentation
from Zope.App.PageTemplate.SimpleViewClass import SimpleViewClass


class EditView(BrowserView):
    """Simple edit-view base class

    Subclasses should provide a schema attribute defining the schema
    to be edited.
    """

    errors = ()
    label = ''

    generated_form = index = ViewPageTemplateFile('edit.pt')

    def __init__(self, context, request):
        super(EditView, self).__init__(context, request)
        setUpEditWidgets(self, self.schema)

    def setPrefix(self, prefix):
        for widget in self.widgets():
            widget.setPrefix(prefix)

    def __call__(self, *args, **kw):
        return self.index(*args, **kw)

    def widgets(self):
        return [getattr(self, name)
                for name in fieldNames(self.schema)
                ]

    def apply_update(self, data):
        """Apply data updates

        Return true if data were unchanged and false otherwise.
        This sounds backwards, but it allows lazy implementations to
        avoid tracking changes.
        """
            
        content = self.context

        errors = []
        unchanged = True

        for name in data:
            # OK, we really got a field
            try:
                newvalue = data[name]

                # We want to see if the data changes. Unfortunately,
                # we don't know enough to know that we won't get some
                # strange error, so we'll carefully ignore errors and
                # assume we should update the data if we can't be sure
                # it's the same.

                change = True
                try:
                    # Use self as a marker
                    change = getattr(content, name, self) != newvalue
                except:
                    pass

                if change:
                    setattr(content, name, data[name])
                    unchanged = False

            except Exception, v:
                errors.append(v)

        if errors:
            raise WidgetsError(*errors)

        return unchanged

    def update(self):
        if "save_submit" in self.request:
            unchanged = True
            try:
                data = getWidgetsData(self, self.schema, required=0)
                unchanged = self.apply_update(data)
            except WidgetsError, errors:
                self.errors = errors
                return u"An error occured."
            except Exception, v:
                self.errors = (v, )
                return u"An error occured."
            else:
                setUpEditWidgets(self, self.schema, force=1)
                if not unchanged:
                    return "Updated %s" % datetime.utcnow()

        return ''

    

def EditViewFactory(name, schema, label, permission, layer,
                    template, class_, for_):

    if class_ is None:
        bases = EditView,
    else:
        bases = class_, EditView
    
    class_  = SimpleViewClass(
        template,
        used_for = schema, bases = bases
        )

    class_.schema = schema
    class_.label = label

    defineChecker(class_,
                  NamesChecker(
                    ("__call__", "__getitem__", "browserDefault"),
                    permission,
                    )
                  )

    provideView(for_, name, IBrowserPresentation, class_, layer)
                  
        

def directive(_context, name, schema, label,
              permission = 'Zope.Public', layer = "default",
              class_ = None, for_ = None,
              template = None):

    schema = _context.resolve(schema)
    if for_ is None:
        for_ = schema
    else:
        for_ = _context.resolve(for_)
    if class_ is not None:
        class_ = _context.resolve(class_)
    if template is not None:
        template = _context.path(template)
    else:
        template = 'edit.pt'

    template = str(template)

    return [
        Action(
        discriminator = ('http://namespaces.zope.org/form/edit',
                         name, for_, layer),
        callable = EditViewFactory,
        args = (name, schema, label, permission, layer, template, class_,
                for_),
        )
        ]




=== Zope3/lib/python/Zope/App/Forms/Browser/__init__.py 1.1 => 1.2 ===
--- /dev/null	Mon Nov 11 15:29:58 2002
+++ Zope3/lib/python/Zope/App/Forms/Browser/__init__.py	Mon Nov 11 15:29:58 2002
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+# 
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+# 
+##############################################################################


=== Added File Zope3/lib/python/Zope/App/Forms/Browser/edit.pt ===
<html metal:use-macro="views/standard_macros/page">
  <body>
  <div metal:fill-slot="body">

  <div metal:define-macro="body">

  <h1 tal:condition="view/label"
      tal:content="view/label">Edit something</h1>

    <p tal:define="status view/update"
       tal:condition="status"
       tal:content="status" />

    <div tal:condition="view/errors">
       <ul>
          <li tal:repeat="error view/errors">
             <strong tal:content="error/__class__">
                Error Type</strong>:
             <span tal:content="error">Error text</span>
          </li>
       </ul>
    </div>

    <form action="." tal:attributes="action request/URL" method="POST"
          enctype="multipart/form-data"
          >
      <table width="100%" border="0">
      <tr metal:define-slot="extra_top" tal:replace="nothing">
          <td>Extra top</td>
          <td><input type="text" style="width:100%" /></td>
      </tr>
      <tr metal:define-macro="widget_rows" tal:repeat="widget view/widgets"
          tal:content="structure widget/row">
          <td>Name</td>
          <td><input type="text" style="width:100%" /></td>
      </tr>
      <tr metal:define-slot="extra_bottom" tal:replace="nothing">
          <td>Extra bottom</td>
          <td><input type="text" style="width:100%" /></td>
      </tr>
      </table>
      <input type="submit"  value="Refresh" />
      <input type="submit" name="save_submit"  value="Save Changes" />

    </form>

  </div>

  </div>
  </body>

</html>


=== Added File Zope3/lib/python/Zope/App/Forms/Browser/meta.zcml ===
<zopeConfigure xmlns='http://namespaces.zope.org/zope'>

  <directives namespace="http://namespaces.zope.org/form">

    <directive
       name="edit" 
       attributes="name schema label for layer permission class template"
       handler=".EditView.directive"
       />

  </directives>

</zopeConfigure>