[z3-checkins] r8668 - in z3/Five/branch/regebro-addform_directive: . tests/products/FiveTest tests/products/FiveTest/www

regebro at codespeak.net regebro at codespeak.net
Fri Jan 28 18:08:19 MET 2005


Author: regebro
Date: Fri Jan 28 18:08:19 2005
New Revision: 8668

Added:
   z3/Five/branch/regebro-addform_directive/add.pt   (contents, props changed)
   z3/Five/branch/regebro-addform_directive/tests/products/FiveTest/www/fieldSimpleContentAdd.zpt   (contents, props changed)
Modified:
   z3/Five/branch/regebro-addform_directive/browser.py
   z3/Five/branch/regebro-addform_directive/browserconfigure.py
   z3/Five/branch/regebro-addform_directive/edit.pt
   z3/Five/branch/regebro-addform_directive/meta.zcml
   z3/Five/branch/regebro-addform_directive/metaconfigure.py
   z3/Five/branch/regebro-addform_directive/tests/products/FiveTest/configure.zcml
Log:
addform + factory directive

Added: z3/Five/branch/regebro-addform_directive/add.pt
==============================================================================
--- (empty file)
+++ z3/Five/branch/regebro-addform_directive/add.pt	Fri Jan 28 18:08:19 2005
@@ -0,0 +1,70 @@
+<html>
+  <body>
+
+  <div metal:define-macro="addform">
+
+    <form action="." tal:attributes="action request/URL" method="post"
+          enctype="multipart/form-data">
+
+      <div metal:define-macro="formbody">
+
+        <h3 tal:condition="view/label"
+            tal:content="view/label"
+            metal:define-slot="heading"
+            >Edit something</h3>
+
+        <p tal:define="status view/update"
+           tal:condition="status"
+           tal:content="status" />
+
+        <p tal:condition="view/errors" i18n:translate="">
+          There are <strong tal:content="python:len(view.errors)"
+                            i18n:name="num_errors">6</strong> input errors.
+        </p>
+
+        <div metal:define-slot="extra_info" tal:replace="nothing">
+        </div>
+
+        <div class="row" metal:define-slot="extra_top" tal:replace="nothing">
+            <div class="label">Extra top</div>
+            <div class="label"><input type="text" style="width:100%" /></div>
+        </div>
+
+        <div metal:use-macro="context/@@widget_macros/widget_rows" />
+
+        <div class="separator"></div>
+
+        <div class="row"
+            metal:define-slot="extra_bottom" tal:replace="nothing">
+          <div class="label">Extra bottom</div>
+          <div class="field"><input type="text" style="width:100%" /></div>
+        </div>
+
+        <div class="separator"></div>
+
+      </div>
+      <br/><br/>
+      <div class="row">
+        <div class="controls"><hr />
+          <input type='submit' value='Refresh'
+                 i18n:attributes='value refresh-button' />
+          <input type='submit' value='Add' name='UPDATE_SUBMIT'
+                 i18n:attributes='value add-button' />
+          <span tal:condition="context/nameAllowed|nothing" tal:omit-tag="">
+               &nbsp;&nbsp;<b i18n:translate="">Object Name</b>&nbsp;&nbsp;
+              <input type='text' name='add_input_name'
+                     tal:attributes="value context/contentName" />
+          </span>
+        </div>
+      </div>
+
+      <div class="row" metal:define-slot="extra_buttons" tal:replace="nothing">
+      </div>
+
+      <div class="separator"></div>
+    </form>
+  </div>
+  </body>
+
+</html>
+

Modified: z3/Five/branch/regebro-addform_directive/browser.py
==============================================================================
--- z3/Five/branch/regebro-addform_directive/browser.py	(original)
+++ z3/Five/branch/regebro-addform_directive/browser.py	Fri Jan 28 18:08:19 2005
@@ -25,8 +25,12 @@
 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.utility import setUpWidgets, getWidgetsData
 from zope.app.form.browser.submit import Update
+from zope.app.form.interfaces import IInputWidget, WidgetsError
 from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
+from zope.event import notify
+from zope.app.event.objectevent import ObjectCreatedEvent
 
 
 class BrowserView(Acquisition.Explicit):
@@ -160,7 +164,7 @@
                     notify(ObjectModifiedEvent(content))
             except WidgetsError, errors:
                 self.errors = errors
-                status = _("An error occured.")
+                status = "An error occured."
                 get_transaction().abort()
             else:
                 setUpEditWidgets(self, self.schema, source=self.adapted,
@@ -179,6 +183,282 @@
         self.update_status = status
         return status
 
+class AddView(EditView):
+    """Simple edit-view base class.
+
+    Subclasses should provide a schema attribute defining the schema
+    to be edited.
+    """
+
+    def _setUpWidgets(self):
+        setUpWidgets(self, self.schema, IInputWidget, names=self.fieldNames)
+
+    def update(self):
+
+        if self.update_status is not None:
+            # We've been called before. Just return the previous result.
+            return self.update_status
+
+        if Update in self.request.form.keys():
+
+            self.update_status = ''
+            try:
+                data = getWidgetsData(self, self.schema, names=self.fieldNames)
+                self.createAndAdd(data)
+            except WidgetsError, errors:
+                self.errors = errors
+                self.update_status = "An error occured."
+                return self.update_status
+
+            self.request.response.redirect(self.context.absolute_url())
+
+        return self.update_status
+
+    def create(self, *args, **kw):
+        """Do the actual instantiation."""
+        return self._factory(*args, **kw)
+
+    def createAndAdd(self, data):
+        """Add the desired object using the data in the data argument.
+
+        The data argument is a dictionary with the data entered in the form.
+        """
+        args = []
+        if self._arguments:
+            for name in self._arguments:
+                args.append(data[name])
+
+        kw = {}
+        if self._keyword_arguments:
+            for name in self._keyword_arguments:
+                if name in data:
+                    kw[str(name)] = data[name]
+
+        content = self.create(*args, **kw)
+        adapted = self.schema(content)
+
+        errors = []
+
+        if self._set_before_add:
+            for name in self._set_before_add:
+                if name in data:
+                    field = self.schema[name]
+                    try:
+                        field.set(adapted, data[name])
+                    except ValidationError:
+                        errors.append(sys.exc_info()[1])
+
+        if errors:
+            raise WidgetsError(*errors)
+
+        notify(ObjectCreatedEvent(content))
+
+        content = self.add(content)
+
+        adapted = self.schema(content)
+
+        if self._set_after_add:
+            for name in self._set_after_add:
+                if name in data:
+                    field = self.schema[name]
+                    try:
+                        field.set(adapted, data[name])
+                    except ValidationError:
+                        errors.append(sys.exc_info()[1])
+
+        if errors:
+            raise WidgetsError(*errors)
+
+        return content
+
+    def add(self, content):
+        self.context._setObject(content.getId(), content)
+        return self.context._getOb(content.getId())
+
+class AddView(EditView):
+    """Simple edit-view base class.
+
+    Subclasses should provide a schema attribute defining the schema
+    to be edited.
+    """
+
+    def _setUpWidgets(self):
+        setUpWidgets(self, self.schema, IInputWidget, names=self.fieldNames)
+
+    def update(self):
+
+        if self.update_status is not None:
+            # We've been called before. Just return the previous result.
+            return self.update_status
+
+        if Update in self.request.form.keys():
+
+            self.update_status = ''
+            try:
+                data = getWidgetsData(self, self.schema, names=self.fieldNames)
+                self.createAndAdd(data)
+            except WidgetsError, errors:
+                self.errors = errors
+                self.update_status = "An error occured."
+                return self.update_status
+
+            self.request.response.redirect(self.context.absolute_url())
+
+        return self.update_status
+
+    def create(self, *args, **kw):
+        """Do the actual instantiation."""
+        return self._factory(*args, **kw)
+
+    def createAndAdd(self, data):
+        """Add the desired object using the data in the data argument.
+
+        The data argument is a dictionary with the data entered in the form.
+        """
+        args = []
+        if self._arguments:
+            for name in self._arguments:
+                args.append(data[name])
+
+        kw = {}
+        if self._keyword_arguments:
+            for name in self._keyword_arguments:
+                if name in data:
+                    kw[str(name)] = data[name]
+
+        content = self.create(*args, **kw)
+        adapted = self.schema(content)
+
+        errors = []
+
+        if self._set_before_add:
+            for name in self._set_before_add:
+                if name in data:
+                    field = self.schema[name]
+                    try:
+                        field.set(adapted, data[name])
+                    except ValidationError:
+                        errors.append(sys.exc_info()[1])
+
+        if errors:
+            raise WidgetsError(*errors)
+
+        notify(ObjectCreatedEvent(content))
+
+        content = self.add(content)
+
+        adapted = self.schema(content)
+
+        if self._set_after_add:
+            for name in self._set_after_add:
+                if name in data:
+                    field = self.schema[name]
+                    try:
+                        field.set(adapted, data[name])
+                    except ValidationError:
+                        errors.append(sys.exc_info()[1])
+
+        if errors:
+            raise WidgetsError(*errors)
+
+        return content
+
+    def add(self, content):
+        self.context._setObject(content.getId(), content)
+        return self.context._getOb(content.getId())
+
+class AddView(EditView):
+    """Simple edit-view base class.
+
+    Subclasses should provide a schema attribute defining the schema
+    to be edited.
+    """
+
+    def _setUpWidgets(self):
+        setUpWidgets(self, self.schema, IInputWidget, names=self.fieldNames)
+
+    def update(self):
+
+        if self.update_status is not None:
+            # We've been called before. Just return the previous result.
+            return self.update_status
+
+        if Update in self.request.form.keys():
+
+            self.update_status = ''
+            try:
+                data = getWidgetsData(self, self.schema, names=self.fieldNames)
+                self.createAndAdd(data)
+            except WidgetsError, errors:
+                self.errors = errors
+                self.update_status = "An error occured."
+                return self.update_status
+
+            self.request.response.redirect(self.context.absolute_url())
+
+        return self.update_status
+
+    def create(self, *args, **kw):
+        """Do the actual instantiation."""
+        return self._factory(*args, **kw)
+
+    def createAndAdd(self, data):
+        """Add the desired object using the data in the data argument.
+
+        The data argument is a dictionary with the data entered in the form.
+        """
+        args = []
+        if self._arguments:
+            for name in self._arguments:
+                args.append(data[name])
+
+        kw = {}
+        if self._keyword_arguments:
+            for name in self._keyword_arguments:
+                if name in data:
+                    kw[str(name)] = data[name]
+
+        content = self.create(*args, **kw)
+        adapted = self.schema(content)
+
+        errors = []
+
+        if self._set_before_add:
+            for name in self._set_before_add:
+                if name in data:
+                    field = self.schema[name]
+                    try:
+                        field.set(adapted, data[name])
+                    except ValidationError:
+                        errors.append(sys.exc_info()[1])
+
+        if errors:
+            raise WidgetsError(*errors)
+
+        notify(ObjectCreatedEvent(content))
+
+        content = self.add(content)
+
+        adapted = self.schema(content)
+
+        if self._set_after_add:
+            for name in self._set_after_add:
+                if name in data:
+                    field = self.schema[name]
+                    try:
+                        field.set(adapted, data[name])
+                    except ValidationError:
+                        errors.append(sys.exc_info()[1])
+
+        if errors:
+            raise WidgetsError(*errors)
+
+        return content
+
+    def add(self, content):
+        self.context._setObject(content.getId(), content)
+        return self.context._getOb(content.getId())
+
 
 class Macros:
 

Modified: z3/Five/branch/regebro-addform_directive/browserconfigure.py
==============================================================================
--- z3/Five/branch/regebro-addform_directive/browserconfigure.py	(original)
+++ z3/Five/branch/regebro-addform_directive/browserconfigure.py	Fri Jan 28 18:08:19 2005
@@ -13,7 +13,7 @@
 
 $Id$
 """
-import os
+import os, sys
 
 from zope.interface import Interface
 from zope.component import getGlobalService, ComponentLookupError
@@ -25,12 +25,13 @@
 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.container.interfaces import IAdding
 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, EditView
+from browser import BrowserView, EditView, AddView
 from metaclass import makeClass
 from security import getSecurityInfo, protectClass, protectName, initializeClass
 from globalbrowsermenuservice import menuItemDirective
@@ -374,6 +375,129 @@
             kw={'menu': self.menu},
         )
 
+
+def AddViewFactory(name, schema, label, permission, layer,
+                   template, default_template, bases, for_,
+                   fields, content_factory, arguments,
+                   keyword_arguments, set_before_add, set_after_add,
+                   menu=u''):
+
+    s = getGlobalService(Presentation)
+    class_ = makeClassForTemplate(template, used_for=schema, bases=bases)
+
+    class_.schema = schema
+    class_.label = label
+    class_.fieldNames = fields
+    class_._factory = content_factory
+    class_._arguments = arguments
+    class_._keyword_arguments = keyword_arguments
+    class_._set_before_add = set_before_add
+    class_._set_after_add = set_after_add
+
+    class_.generated_form = ViewPageTemplateFile(default_template)
+
+#     defineChecker(class_,
+#                   NamesChecker(
+#                     ("__call__", "__getitem__",
+#                      "browserDefault", "publishTraverse"),
+#                     permission,
+#                     )
+#                   )
+
+    s.provideView(for_, name, IBrowserRequest, class_, layer)
+
+class AddFormDirective(BaseFormDirective):
+
+    view = AddView
+    default_template = 'add.pt'
+    for_ = IAdding
+
+    # default add form information
+    description = None
+    content_factory = None
+    arguments = None
+    keyword_arguments = None
+    set_before_add = None
+    set_after_add = None
+
+    def _handle_menu(self):
+        if self.menu or self.title:
+            if (not self.menu) or (not self.title):
+                raise ValueError("If either menu or title are specified, "
+                                 "they must both be specified")
+            # Add forms are really for IAdding components, so do not use
+            # for=self.schema.
+            menuItemDirective(
+                self._context, self.menu, self.for_, '@@' + self.name,
+                self.title, permission=self.permission,
+                description=self.description)
+
+    def _handle_arguments(self, leftover=None):
+        schema = self.schema
+        fields = self.fields
+        arguments = self.arguments
+        keyword_arguments = self.keyword_arguments
+        set_before_add = self.set_before_add
+        set_after_add = self.set_after_add
+
+        if leftover is None:
+            leftover = fields
+
+        if arguments:
+            missing = [n for n in arguments if n not in fields]
+            if missing:
+                raise ValueError("Some arguments are not included in the form",
+                                 missing)
+            optional = [n for n in arguments if not schema[n].required]
+            if optional:
+                raise ValueError("Some arguments are optional, use"
+                                 " keyword_arguments for them",
+                                 optional)
+            leftover = [n for n in leftover if n not in arguments]
+
+        if keyword_arguments:
+            missing = [n for n in keyword_arguments if n not in fields]
+            if missing:
+                raise ValueError(
+                    "Some keyword_arguments are not included in the form",
+                    missing)
+            leftover = [n for n in leftover if n not in keyword_arguments]
+
+        if set_before_add:
+            missing = [n for n in set_before_add if n not in fields]
+            if missing:
+                raise ValueError(
+                    "Some set_before_add are not included in the form",
+                    missing)
+            leftover = [n for n in leftover if n not in set_before_add]
+
+        if set_after_add:
+            missing = [n for n in set_after_add if n not in fields]
+            if missing:
+                raise ValueError(
+                    "Some set_after_add are not included in the form",
+                    missing)
+            leftover = [n for n in leftover if n not in set_after_add]
+
+            self.set_after_add += leftover
+
+        else:
+            self.set_after_add = leftover
+
+    def __call__(self):
+        self._processWidgets()
+        self._handle_menu()
+        self._handle_arguments()
+
+        self._context.action(
+            discriminator=self._discriminator(),
+            callable=AddViewFactory,
+            args=self._args()+(self.content_factory, self.arguments,
+                                 self.keyword_arguments,
+                                 self.set_before_add, self.set_after_add),
+            kw={'menu': self.menu},
+            )
+
 #
 # mixin classes / class factories
 #

Modified: z3/Five/branch/regebro-addform_directive/edit.pt
==============================================================================
--- z3/Five/branch/regebro-addform_directive/edit.pt	(original)
+++ z3/Five/branch/regebro-addform_directive/edit.pt	Fri Jan 28 18:08:19 2005
@@ -1,7 +1,6 @@
 <tal:tag condition="view/update"/>
-<html>
-  <body>
-  <div>
+<html metal:use-macro="here/main_template/macros/master">
+  <body metal:fill-slot="main">
 
   <div metal:define-macro="body">
 
@@ -61,8 +60,6 @@
     </form>
 
   </div>
-
-  </div>
   </body>
 
 </html>

Modified: z3/Five/branch/regebro-addform_directive/meta.zcml
==============================================================================
--- z3/Five/branch/regebro-addform_directive/meta.zcml	(original)
+++ z3/Five/branch/regebro-addform_directive/meta.zcml	Fri Jan 28 18:08:19 2005
@@ -79,8 +79,19 @@
           schema="zope.app.component.metadirectives.IAllowSubdirective"
           />
 
+      <meta:subdirective
+          name="factory"
+          schema="zope.app.component.metadirectives.IFactorySubdirective"
+          />
+
     </meta:complexDirective>
 
+    <meta:directive
+        name="factory"
+        schema="zope.app.component.metadirectives.IFactoryDirective"
+        handler="zope.app.component.metaconfigure.factory"
+        />
+
   </meta:directives>
 
   <meta:directives namespace="http://namespaces.zope.org/browser">
@@ -179,6 +190,19 @@
 
     </meta:complexDirective>
 
+    <meta:complexDirective
+        name="addform"
+        schema="zope.app.form.browser.metadirectives.IAddFormDirective"
+        handler=".browserconfigure.AddFormDirective"
+        >
+
+      <meta:subdirective
+          name="widget"
+          schema="zope.app.form.browser.metadirectives.IWidgetSubdirective"
+          />
+
+    </meta:complexDirective>
+
   </meta:directives>
 
 

Modified: z3/Five/branch/regebro-addform_directive/metaconfigure.py
==============================================================================
--- z3/Five/branch/regebro-addform_directive/metaconfigure.py	(original)
+++ z3/Five/branch/regebro-addform_directive/metaconfigure.py	Fri Jan 28 18:08:19 2005
@@ -14,6 +14,8 @@
 
 from zope.interface import classImplements
 from zope.configuration.exceptions import ConfigurationError
+from zope.component.factory import Factory
+from zope.app.component.metaconfigure import factory
 
 from security import CheckerPublic
 from security import protectName, initializeClass
@@ -80,3 +82,16 @@
             callable = initializeClass,
             args = (self.__class,)
             )
+
+    def factory(self, _context, id=None, title="", description=''):
+        """Register a zmi factory for this class"""
+
+        id = id or self.__id
+        factoryObj = Factory(self.__class, title, description)
+
+        # note factories are all in one pile, services and content,
+        # so addable names must also act as if they were all in the
+        # same namespace, despite the service/content division
+        factory(_context, factoryObj, id, title, description)
+
+

Modified: z3/Five/branch/regebro-addform_directive/tests/products/FiveTest/configure.zcml
==============================================================================
--- z3/Five/branch/regebro-addform_directive/tests/products/FiveTest/configure.zcml	(original)
+++ z3/Five/branch/regebro-addform_directive/tests/products/FiveTest/configure.zcml	Fri Jan 28 18:08:19 2005
@@ -293,6 +293,12 @@
       permission="zope2.Public"
       />
 
+  <browser:addform
+      schema=".interfaces.IFieldSimpleContent"
+      for=".interfaces.IFieldSimpleContent"
+      name="add.html"
+      permission="zope2.Public"
+      />
   <!-- stuff that we'll override in overrides.zcml -->
 
   <browser:page

Added: z3/Five/branch/regebro-addform_directive/tests/products/FiveTest/www/fieldSimpleContentAdd.zpt
==============================================================================
--- (empty file)
+++ z3/Five/branch/regebro-addform_directive/tests/products/FiveTest/www/fieldSimpleContentAdd.zpt	Fri Jan 28 18:08:19 2005
@@ -0,0 +1,45 @@
+<h1 tal:replace="structure here/manage_page_header">Header</h1>
+
+<h2 tal:define="form_title string:Add Field Simple Content"
+    tal:replace="structure here/manage_form_title">Form Title</h2>
+
+<p class="form-help">
+Add Simple Content
+</p>
+
+<form action="manage_addFieldSimpleContent" method="post">
+<table cellspacing="0" cellpadding="2" border="0">
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-label">
+    Id
+    </div>
+    </td>
+    <td align="left" valign="top">
+    <input type="text" name="id" size="40" />
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-label">
+    Title
+    </div>
+    </td>
+    <td align="left" valign="top">
+    <input type="text" name="title" size="40" />
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="top">
+    </td>
+    <td align="left" valign="top">
+    <div class="form-element">
+    <input class="form-element" type="submit" name="submit_add"
+     value=" Add " />
+    </div>
+    </td>
+  </tr>
+</table>
+</form>
+
+<h1 tal:replace="structure here/manage_page_footer">Footer</h1>


More information about the z3-checkins mailing list