[z3-checkins] r8282 - in z3/Five/trunk: . tests/products/FiveTest

regebro at codespeak.net regebro at codespeak.net
Fri Jan 14 19:24:08 MET 2005


Author: regebro
Date: Fri Jan 14 19:24:08 2005
New Revision: 8282

Added:
   z3/Five/trunk/edit.pt   (props changed)
      - copied unchanged from r8221, z3/Five/branch/regebro-forms_support/edit.pt
Modified:
   z3/Five/trunk/CHANGES.txt
   z3/Five/trunk/browser.py
   z3/Five/trunk/browserconfigure.py
   z3/Five/trunk/configure.zcml
   z3/Five/trunk/meta.zcml
   z3/Five/trunk/tests/products/FiveTest/__init__.py
   z3/Five/trunk/tests/products/FiveTest/configure.zcml
   z3/Five/trunk/tests/products/FiveTest/interfaces.py
   z3/Five/trunk/tests/products/FiveTest/simplecontent.py
Log:
Support for browser:editform

Modified: z3/Five/trunk/CHANGES.txt
==============================================================================
--- z3/Five/trunk/CHANGES.txt	(original)
+++ z3/Five/trunk/CHANGES.txt	Fri Jan 14 19:24:08 2005
@@ -20,6 +20,8 @@
   zope.security.checkPermission, which checks if the current user
   has a permission on an object.
 
+* Support for browser:editform. You can now use schemas for editing.
+
 
 Five 0.2b
 ---------

Modified: z3/Five/trunk/browser.py
==============================================================================
--- z3/Five/trunk/browser.py	(original)
+++ z3/Five/trunk/browser.py	Fri Jan 14 19:24:08 2005
@@ -16,11 +16,17 @@
 from AccessControl import ClassSecurityInfo
 from Globals import InitializeClass
 from interfaces import ITraversable
+from datetime import datetime
 from zope.interface import implements
 from zope.interface.common.mapping import IItemMapping
 from zope.component import getView
 from zope.component import getViewProviding
 from zope.app.traversing.browser.interfaces import IAbsoluteURL
+from zope.app.location.interfaces import ILocation
+from zope.app.location import LocationProxy
+from zope.app.form.utility import setUpEditWidgets, applyWidgetsChanges
+from zope.app.form.browser.submit import Update
+from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
 
 
 class BrowserView(Acquisition.Explicit):
@@ -89,6 +95,91 @@
                  'url': context.absolute_url()
                  },)
 
+
+class EditView(BrowserView):
+    """Simple edit-view base class
+
+    Subclasses should provide a schema attribute defining the schema
+    to be edited.
+    """
+
+    errors = ()
+    update_status = None
+    label = ''
+
+    # Fall-back field names computes from schema
+    fieldNames = property(lambda self: getFieldNamesInOrder(self.schema))
+    # Fall-back template
+    generated_form = ViewPageTemplateFile('edit.pt')
+
+    def __init__(self, context, request):
+        BrowserView.__init__(self, context, request)
+        self._setUpWidgets()
+
+    def _setUpWidgets(self):
+        adapted = self.schema(self.context)
+        if adapted is not self.context:
+            if not ILocation.providedBy(adapted):
+                adapted = LocationProxy(adapted)
+            adapted.__parent__ = self.context
+        self.adapted = adapted
+        setUpEditWidgets(self, self.schema, source=self.adapted,
+                         names=self.fieldNames)
+
+    def setPrefix(self, prefix):
+        for widget in self.widgets():
+            widget.setPrefix(prefix)
+
+    def widgets(self):
+        return [getattr(self, name+'_widget')
+                for name in self.fieldNames]
+
+    def changed(self):
+        # This method is overridden to execute logic *after* changes
+        # have been made.
+        pass
+
+    def update(self):
+        if self.update_status is not None:
+            # We've been called before. Just return the status we previously
+            # computed.
+            return self.update_status
+
+        status = ''
+
+        content = self.adapted
+
+        if Update in self.request.form.keys():
+            changed = False
+            try:
+                changed = applyWidgetsChanges(self, self.schema,
+                    target=content, names=self.fieldNames)
+                # We should not generate events when an adapter is used.
+                # That's the adapter's job.
+                if changed and self.context is self.adapted:
+                    notify(ObjectModifiedEvent(content))
+            except WidgetsError, errors:
+                self.errors = errors
+                status = _("An error occured.")
+                get_transaction().abort()
+            else:
+                setUpEditWidgets(self, self.schema, source=self.adapted,
+                                 ignoreStickyValues=True,
+                                 names=self.fieldNames)
+                if changed:
+                    self.changed()
+                    # XXX: Needs i18n support:
+                    # formatter = self.request.locale.dates.getFormatter(
+                    #     'dateTime', 'medium')
+                    # status = _("Updated on ${date_time}")
+                    # status.mapping = {'date_time': formatter.format(
+                    #     datetime.utcnow())}
+                    status = "Updated on %s" % str(datetime.utcnow())
+
+        self.update_status = status
+        return status
+
+
 class Macros:
 
     implements(IItemMapping)
@@ -115,3 +206,4 @@
         raise KeyError, key
 
 class StandardMacros(BrowserView, Macros): pass
+

Modified: z3/Five/trunk/browserconfigure.py
==============================================================================
--- z3/Five/trunk/browserconfigure.py	(original)
+++ z3/Five/trunk/browserconfigure.py	Fri Jan 14 19:24:08 2005
@@ -25,13 +25,15 @@
 from zope.app.publisher.browser.viewmeta import pages as zope_app_pages
 from zope.app.component.metaconfigure import handler
 from zope.app.component.interface import provideInterface
+from zope.app.form.browser.metaconfigure import BaseFormDirective
 
 from resource import FileResourceFactory, ImageResourceFactory
 from resource import PageTemplateResourceFactory
 from resource import DirectoryResourceFactory
-from browser import BrowserView
+from browser import BrowserView, EditView
 from metaclass import makeClass
 from security import getSecurityInfo, protectClass, protectName, initializeClass
+from globalbrowsermenuservice import menuItemDirective
 
 class FivePageTemplateFile(ViewPageTemplateFile):
 
@@ -298,6 +300,60 @@
             args = (new_class,)
             )
 
+
+#
+# Form generation from schema
+#
+def EditViewFactory(name, schema, label, permission, layer,
+                    template, default_template, bases, for_, fields,
+                    fulledit_path=None, fulledit_label=None, menu=u''):
+    s = getGlobalService(Presentation)
+    class_ = makeClassForTemplate(template, used_for=schema, bases=bases)
+    class_.schema = schema
+    class_.label = label
+    class_.fieldNames = fields
+
+    class_.fulledit_path = fulledit_path
+    if fulledit_path and (fulledit_label is None):
+        fulledit_label = "Full edit"
+
+    class_.fulledit_label = fulledit_label
+
+    class_.generated_form = ViewPageTemplateFile(default_template)
+
+    # Not the prettiest solution, but it works...
+    class_.__init__ = EditView.__init__
+#     XXX: replace with proper checks
+#     defineChecker(class_,
+#                   NamesChecker(("__call__", "__getitem__",
+#                                 "browserDefault", "publishTraverse"),
+#                                permission))
+
+    s.provideView(for_, name, IBrowserRequest, class_, layer)
+
+
+class EditFormDirective(BaseFormDirective):
+
+    view = EditView
+    default_template = 'edit.pt'
+    title = 'Edit'
+
+    def _handle_menu(self):
+        if self.menu:
+            menuItemDirective(
+                self._context, self.menu, self.for_ or self.schema,
+                '@@' + self.name, self.title, permission=self.permission)
+
+    def __call__(self):
+        self._processWidgets()
+        self._handle_menu()
+        self._context.action(
+            discriminator=self._discriminator(),
+            callable=EditViewFactory,
+            args=self._args(),
+            kw={'menu': self.menu},
+        )
+
 #
 # mixin classes / class factories
 #
@@ -341,3 +397,4 @@
         class_.__used_for__ = used_for
 
     return class_
+

Modified: z3/Five/trunk/configure.zcml
==============================================================================
--- z3/Five/trunk/configure.zcml	(original)
+++ z3/Five/trunk/configure.zcml	Fri Jan 14 19:24:08 2005
@@ -8,6 +8,7 @@
   <include file="permissions.zcml" />
 
   <include package="zope.app.traversing" />
+  <include package="zope.app.form.browser" />
 
   <!-- do 'traditional' traversing by default; needed by ZPT -->
   <adapter

Modified: z3/Five/trunk/meta.zcml
==============================================================================
--- z3/Five/trunk/meta.zcml	(original)
+++ z3/Five/trunk/meta.zcml	Fri Jan 14 19:24:08 2005
@@ -151,7 +151,7 @@
         schema="zope.app.publisher.browser.metadirectives.IMenuItemDirective"
         handler=".globalbrowsermenuservice.menuItemDirective"
         />
-    
+
     <meta:complexDirective
         name="menuItems"
         schema="zope.app.publisher.browser.metadirectives.IMenuItemsDirective"
@@ -162,11 +162,26 @@
           name="menuItem"
           schema="zope.app.publisher.browser.metadirectives.IMenuItemSubdirective"
           />
-    
+
     </meta:complexDirective>
-                
+
+
+    <meta:complexDirective
+        name="editform"
+        schema="zope.app.form.browser.metadirectives.IEditFormDirective"
+        handler=".browserconfigure.EditFormDirective"
+        >
+
+      <meta:subdirective
+          name="widget"
+          schema="zope.app.form.browser.metadirectives.IWidgetSubdirective"
+          />
+
+    </meta:complexDirective>
+
   </meta:directives>
 
+
   <meta:directives namespace="http://namespaces.zope.org/five">
 
     <!-- specific to Five -->

Modified: z3/Five/trunk/tests/products/FiveTest/__init__.py
==============================================================================
--- z3/Five/trunk/tests/products/FiveTest/__init__.py	(original)
+++ z3/Five/trunk/tests/products/FiveTest/__init__.py	Fri Jan 14 19:24:08 2005
@@ -22,6 +22,15 @@
         )
 
     context.registerClass(
-	fancycontent.FancyContent,
-	constructors = (fancycontent.manage_addFancyContent,)
-	)
+        fancycontent.FancyContent,
+        constructors = (fancycontent.manage_addFancyContent,)
+        )
+
+    context.registerClass(
+        simplecontent.FieldSimpleContent,
+        constructors = (simplecontent.manage_addFieldSimpleContentForm,
+                        simplecontent.manage_addFieldSimpleContent,)
+        )
+
+
+

Modified: z3/Five/trunk/tests/products/FiveTest/configure.zcml
==============================================================================
--- z3/Five/trunk/tests/products/FiveTest/configure.zcml	(original)
+++ z3/Five/trunk/tests/products/FiveTest/configure.zcml	Fri Jan 14 19:24:08 2005
@@ -283,6 +283,16 @@
       permission="zope2.ViewManagementScreens"
       />
 
+  <!-- browser forms -->
+  <five:traversable class=".simplecontent.FieldSimpleContent" />
+
+  <browser:editform
+      schema=".interfaces.IFieldSimpleContent"
+      for=".interfaces.IFieldSimpleContent"
+      name="edit.html"
+      permission="zope2.Public"
+      />
+
   <!-- stuff that we'll override in overrides.zcml -->
 
   <browser:page
@@ -308,7 +318,7 @@
       attribute="method"
       permission="zope2.Public"
       />
-    
+
   <!-- browser menu support -->
   <browser:menu
       id="testmenu"
@@ -326,23 +336,23 @@
   <browser:menuItems
       for=".interfaces.ISimpleContent"
       menu="testmenu">
-      
+
       <menuItem
           title="Test Menu Item 2"
           action="parakeet.html"
           description="This is a test menu item"
           permission="zope2.Public"
           />
-      
+
       <menuItem
           title="Test Menu Item 3"
           action="falcon.html"
           description="This is a test menu item"
           permission="zope2.Public"
           />
-          
+
   </browser:menuItems>
-    
+
   <!-- subscribe to all events -->
   <five:sendEvents
       class=".simplecontent.SimpleContent"

Modified: z3/Five/trunk/tests/products/FiveTest/interfaces.py
==============================================================================
--- z3/Five/trunk/tests/products/FiveTest/interfaces.py	(original)
+++ z3/Five/trunk/tests/products/FiveTest/interfaces.py	Fri Jan 14 19:24:08 2005
@@ -1,4 +1,5 @@
 from zope.interface import Interface
+from zope.schema import Text, TextLine
 
 class IAdaptable(Interface):
     """This is a Zope 3 interface.
@@ -35,3 +36,16 @@
 
 class IFancyContent(Interface):
     pass
+
+class IFieldSimpleContent(ISimpleContent):
+    title = TextLine(
+        title=u"Title",
+        description=u"A short description of the event.",
+        default=u"",
+        required=True)
+
+    description = Text(
+        title=u"Description",
+        description=u"A long description of the event.",
+        default=u"",
+        required=False)

Modified: z3/Five/trunk/tests/products/FiveTest/simplecontent.py
==============================================================================
--- z3/Five/trunk/tests/products/FiveTest/simplecontent.py	(original)
+++ z3/Five/trunk/tests/products/FiveTest/simplecontent.py	Fri Jan 14 19:24:08 2005
@@ -5,7 +5,7 @@
 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
 from zope.interface import implements
 from interfaces import ISimpleContent, ICallableSimpleContent,\
-     IIndexSimpleContent
+     IIndexSimpleContent, IFieldSimpleContent
 
 class SimpleContent(SimpleItem):
     implements(ISimpleContent)
@@ -49,6 +49,13 @@
         """ """
         return "Default index_html called"
 
+class FieldSimpleContent(SimpleContent):
+    """A Viewable piece of content with fields"""
+    implements(IFieldSimpleContent)
+
+    meta_type = 'Five FieldSimpleContent'
+
+InitializeClass(FieldSimpleContent)
 
 manage_addSimpleContentForm = PageTemplateFile(
     "www/simpleContentAdd", globals(),
@@ -71,3 +78,13 @@
     id = self._setObject(id, IndexSimpleContent(id, title))
     add_and_edit(self, id, REQUEST)
     return ''
+
+manage_addFieldSimpleContentForm = PageTemplateFile(
+    "www/fieldSimpleContentAdd", globals(),
+    __name__ = 'manage_addFieldSimpleContentForm')
+
+def manage_addFieldSimpleContent(self, id, title, REQUEST=None):
+    """Add the viewable simple content."""
+    id = self._setObject(id, FieldSimpleContent(id, title))
+    add_and_edit(self, id, REQUEST)
+    return ''


More information about the z3-checkins mailing list