[Checkins] SVN: z3c.reference/branches/flash/src/z3c/reference/ refactored to generic form serialization

Bernd Dorn bernd.dorn at lovelysystems.com
Fri Sep 7 08:20:30 EDT 2007


Log message for revision 79521:
  refactored to generic form serialization

Changed:
  U   z3c.reference/branches/flash/src/z3c/reference/README.txt
  U   z3c.reference/branches/flash/src/z3c/reference/browser/README.txt
  A   z3c.reference/branches/flash/src/z3c/reference/browser/serialize.py
  A   z3c.reference/branches/flash/src/z3c/reference/browser/serialize.txt
  U   z3c.reference/branches/flash/src/z3c/reference/browser/tests.py
  U   z3c.reference/branches/flash/src/z3c/reference/browser/views.py
  U   z3c.reference/branches/flash/src/z3c/reference/browser/widget.py
  U   z3c.reference/branches/flash/src/z3c/reference/interfaces.py

-=-
Modified: z3c.reference/branches/flash/src/z3c/reference/README.txt
===================================================================
--- z3c.reference/branches/flash/src/z3c/reference/README.txt	2007-09-07 12:15:50 UTC (rev 79520)
+++ z3c.reference/branches/flash/src/z3c/reference/README.txt	2007-09-07 12:20:29 UTC (rev 79521)
@@ -139,6 +139,7 @@
   ValueError: ('viewReferences', 'field is readonly')
 
 
+
 ViewReferenceSettings
 ---------------------
 

Modified: z3c.reference/branches/flash/src/z3c/reference/browser/README.txt
===================================================================
--- z3c.reference/branches/flash/src/z3c/reference/browser/README.txt	2007-09-07 12:15:50 UTC (rev 79520)
+++ z3c.reference/branches/flash/src/z3c/reference/browser/README.txt	2007-09-07 12:20:29 UTC (rev 79521)
@@ -8,14 +8,19 @@
   >>> from z3c.reference.browser.widget import ViewReferenceWidget
   >>> from z3c.reference.schema import ViewReferenceField
 
+At first we need an interface for the context our widget used for. The
+`ìntro`` filed defines a settingName which is used by the widget to
+get information about which edit form for the reference should
+be used.
+
   >>> class IPage(zope.interface.Interface):
   ...     """Interface for a page."""
   ...
   ...     intro = ViewReferenceField(title=u'Intro',
   ...                                description=u'A intro text',
-  ...                                settingName=u'')
+  ...                                settingName=u'introRefs')
 
-Let's define the IPage object:
+Let's create an IPage implementation.
 
   >>> class Page(object):
   ...
@@ -47,21 +52,10 @@
   >>> boundField = field.bind(page)
   >>> widget = ViewReferenceWidget(boundField, request)
 
-Now let's see how such a widget looks like if we render them::
+Now let's see how such a widget looks like if we render it with no value.
 
-  >>> print widget() # doctest: +NORMALIZE_WHITESPACE
-  <a class="popupwindow"
-  href="http://127.0.0.1/Intro/viewReferenceEditor.html?name=field.intro&amp;target=&amp;settingName=&amp;view="
-  id="field.intro.tag" name="field.intro" onclick="" title="Undefined"
-  rel="window">Undefined</a><input class="hiddenType"
-  id="field.intro.view" name="field.intro.view" type="hidden" value=""
-  rel="window" /><input class="hiddenType" id="field.intro.target"
-  name="field.intro.target" type="hidden" value="" rel="window"
-  /><input class="hiddenType" id="field.intro.title"
-  name="field.intro.title" type="hidden" value="" rel="window"
-  /><input class="hiddenType" id="field.intro.description"
-  name="field.intro.description" type="hidden" value="" rel="window"
-  />
+  >>> print widget()
+  <a class="popupwindow" href="http://127.0.0.1/Intro/viewReferenceEditor.html?target=&amp;settingName=introRefs&amp;name=field.intro" id="field.intro.tag" name="field.intro" onclick="" title="Undefined" rel="window">Undefined</a><input class="hiddenType" id="field.intro.target" name="field.intro.target" type="hidden" value="" rel="window" /><input class="hiddenType" id="field.intro.formData" name="field.intro.formData" type="hidden" value="" rel="window" />
 
 If we store a empty request/form we will get the following error::
 
@@ -89,12 +83,78 @@
   >>> intids = zope.component.getUtility(IIntIds)
   >>> oid = intids.register(text)
 
+Let us assign the text object here, so we can look at what the widget
+renders if a target is defined.
+
+  >>> from z3c.reference.reference import ViewReference
+  >>> vr = ViewReference()
+  >>> vr.target = text
+  >>> page.intro = vr
+
+  >>> field = IPage['intro']
+  >>> boundField = field.bind(page)
+  >>> request = TestRequest()
+  >>> widget = ViewReferenceWidget(boundField, request)
+  >>> widget.setRenderedValue(page.intro)
+  >>> print widget()
+  Traceback (most recent call last):
+  ...
+  ComponentLookupError: ((<Text object at ...>,
+  <zope.publisher.browser.TestRequest instance URL=http://127.0.0.1>),
+  <InterfaceClass z3c.reference.interfaces.IViewReferenceEditor>, u'introRefs')
+
+Ups, we get an Error. We need a editor form for the given settings for
+the target object. Let's create one that edits basic dublin core data.
+
+  >>> from zope.formlib import form
+  >>> from zope.dublincore.interfaces import IZopeDublinCore
+  >>> from z3c.reference.interfaces import IViewReference
+  >>> class IntroRefsEditForm(form.EditForm):
+  ...     form_fields = form.Fields(IZopeDublinCore,
+  ...     IViewReference).select('title', 'description', 'view')
+
+And register it ...
+
+  >>> from z3c.reference.interfaces import IViewReferenceEditor
+  >>> from zope.publisher.interfaces.browser import IBrowserRequest
+  >>> zope.component.provideAdapter(IntroRefsEditForm,
+  ...     (zope.interface.Interface, IBrowserRequest),
+  ...     IViewReferenceEditor,
+  ...     name=u'introRefs')
+
+We also need to register the widgets.
+
+  >>> from zope.schema.interfaces import ITextLine, IText
+  >>> from zope.app.form.browser import TextWidget, TextAreaWidget
+  >>> from zope.app.form.browser.interfaces import ISimpleInputWidget
+  >>> from zope.app.form.browser.interfaces import ITextBrowserWidget
+  >>> zope.component.provideAdapter(TextWidget,
+  ...     (ITextLine, IBrowserRequest), ITextBrowserWidget)
+  >>> zope.component.provideAdapter(TextAreaWidget,
+  ...     (IText, IBrowserRequest), ISimpleInputWidget)
+
+So there is no formData for now, because we have no data on the reference.
+
+
+  >>> print widget()
+  <...name="field.intro.formData"
+  ...value="form.title=&amp;form.view=&amp;form.description="...
+
+Let us write some data to it.
+
+  >>> IZopeDublinCore(vr).title = u"The DC Title"
+  >>> IZopeDublinCore(vr).description = u"The DC Description"
+  >>> print widget()
+  <...
+  value="form.title=The+DC+Title&amp;form.view=&amp;form.description=The+DC+Description"...
+
 Now we can setup a test request and set the values for the widget:
+
+  >>> formData = 'form.view=resized&form.title=New+Title&amp;form.description=New+Description'
   >>> form={'field.intro.target': oid,
-  ...       'field.intro.view': 'ratio=16x9',
-  ...       'field.intro.title': 'My reference',
-  ...       'field.intro.description': 'This is a reference'}
-  >>> request = TestRequest(HTTP_ACCEPT_LANGUAGE='pl', form=form)
+  ...       'field.intro.formData': formData}
+
+  >>> request = TestRequest(form=form)
   >>> widget = ViewReferenceWidget(boundField, request)
   >>> reference = widget._toFieldValue(form)
   >>> reference
@@ -103,14 +163,14 @@
   >>> reference.target is text
   True
 
-  >>> reference.view
-  u'ratio=16x9'
+  >>> IZopeDublinCore(reference).title
+  u'New Title'
 
-  >>> reference.title
-  u'My reference'
+  >>> IZopeDublinCore(reference).description
+  u'New Description'
 
-  >>> reference.description
-  u'This is a reference'
+  >>> reference.view
+  u'resized'
 
 Let's save the new reference:
 

Added: z3c.reference/branches/flash/src/z3c/reference/browser/serialize.py
===================================================================
--- z3c.reference/branches/flash/src/z3c/reference/browser/serialize.py	                        (rev 0)
+++ z3c.reference/branches/flash/src/z3c/reference/browser/serialize.py	2007-09-07 12:20:29 UTC (rev 79521)
@@ -0,0 +1,22 @@
+import cElementTree
+import urllib
+def serializeForm(html):
+
+    html = '<div>%s</div>' % html
+    elem = cElementTree.fromstring(html)
+    res = []
+    for e in elem.findall('input'):
+        name = e.get('name')
+        value = e.get('value')
+        t = e.get('type')
+        if t not in ('hidden', 'text') or None in (name, value):
+            continue
+        res.append((name, value))
+    for e in elem.findall('textarea'):
+        name = e.get('name')
+        value = e.text or ''
+        if name is None:
+            continue
+        res.append((name, value))
+    return urllib.urlencode(res)
+


Property changes on: z3c.reference/branches/flash/src/z3c/reference/browser/serialize.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.reference/branches/flash/src/z3c/reference/browser/serialize.txt
===================================================================
--- z3c.reference/branches/flash/src/z3c/reference/browser/serialize.txt	                        (rev 0)
+++ z3c.reference/branches/flash/src/z3c/reference/browser/serialize.txt	2007-09-07 12:20:29 UTC (rev 79521)
@@ -0,0 +1,15 @@
+=================
+ Form serializer
+=================
+
+Serializes a form to a query string.
+
+    >>> from z3c.reference.browser.serialize import serializeForm
+
+    >>> html = """<input type="text" value="one" name="m.one"/><br/>"""\
+    ...        """<input type="text" value="two" name="m.two"/>""" \
+    ...        """<textarea name="m.area">tarea</textarea>""" \
+    ...        """<input type="text" value="second" name="m.two"/>"""
+    >>> print serializeForm(html)
+    m.one=one&m.two=two&m.two=second&m.area=tarea
+


Property changes on: z3c.reference/branches/flash/src/z3c/reference/browser/serialize.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: z3c.reference/branches/flash/src/z3c/reference/browser/tests.py
===================================================================
--- z3c.reference/branches/flash/src/z3c/reference/browser/tests.py	2007-09-07 12:15:50 UTC (rev 79520)
+++ z3c.reference/branches/flash/src/z3c/reference/browser/tests.py	2007-09-07 12:20:29 UTC (rev 79521)
@@ -64,6 +64,10 @@
 def test_suite():
     
     return unittest.TestSuite((
+        DocFileSuite('serialize.txt',
+                     setUp=setUp,tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
         DocFileSuite('README.txt',
                      setUp=setUp,tearDown=tearDown,
                      optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,

Modified: z3c.reference/branches/flash/src/z3c/reference/browser/views.py
===================================================================
--- z3c.reference/branches/flash/src/z3c/reference/browser/views.py	2007-09-07 12:15:50 UTC (rev 79520)
+++ z3c.reference/branches/flash/src/z3c/reference/browser/views.py	2007-09-07 12:20:29 UTC (rev 79521)
@@ -144,6 +144,11 @@
         return u''
 
 
+def getEditorView(target, request, settingName):
+    return component.getMultiAdapter(
+        (target, request),
+        interfaces.IViewReferenceEditor, name=settingName)
+
 class ViewReferenceEditorDispatcher(object):
 
     """Return the edit IViewReferenceEditor for the target context
@@ -170,8 +175,6 @@
         intids = component.getUtility(IIntIds)
         obj = intids.queryObject(int(self.targetStr))
         if obj is not None and self.settingNameStr is not None:
-            view = component.queryMultiAdapter((obj, self.request),
-                interfaces.IViewReferenceEditor, name=self.settingNameStr)
-            if view is not None:
-                return view()
+            view = getEditorView(obj, self.request, self.settingNameStr)
+            return view()
         return u''

Modified: z3c.reference/branches/flash/src/z3c/reference/browser/widget.py
===================================================================
--- z3c.reference/branches/flash/src/z3c/reference/browser/widget.py	2007-09-07 12:15:50 UTC (rev 79520)
+++ z3c.reference/branches/flash/src/z3c/reference/browser/widget.py	2007-09-07 12:20:29 UTC (rev 79521)
@@ -23,7 +23,7 @@
 from zope.traversing.browser import absoluteURL
 from zope.traversing.interfaces import TraversalError
 from zope.cachedescriptors.property import Lazy
-
+from zope.publisher.browser import TestRequest
 from zope.app.intid.interfaces import IIntIds
 from zope.app.form.browser.widget import SimpleInputWidget
 from zope.app.form.browser.textwidgets import TextWidget
@@ -33,6 +33,8 @@
 from zc import resourcelibrary
 from z3c.reference import interfaces
 from z3c.reference.reference import ViewReference,ImageReference
+from views import getEditorView
+from serialize import serializeForm
 
 untitled = u'No Link defined'
 undefined = u'Undefined'
@@ -48,7 +50,6 @@
             rc = rc + node.data
     return rc
 
-
 class ViewReferenceWidget(TextWidget):
     """renders an "a" tag with the title and href attributes."""
 
@@ -70,12 +71,29 @@
         """Returns the refrence explorer url."""
         return absoluteURL(self.context.context, self.request) + '/%s?%s' % (
             self.referenceExplorerViewName,
-            urllib.urlencode({'settingName': self.context.settingName,
-                             'target': self.targetValue,
-                             'view': self.viewValue,
-                             'name': self.name}))
+            urllib.urlencode({'settingName' : self.context.settingName,
+                              'target' : self.targetValue,
+                              'name': self.name}))
 
     @property
+    def formDataValue(self):
+        vr = self._getCurrentValue()
+        if vr is None or vr.target is None:
+            return ''
+        klass = getEditorView(vr.target, self.request,
+                              self.context.settingName).__class__
+
+
+        view = klass(vr, TestRequest())
+        view.resetForm()
+        html = ''
+        for widget in view.widgets:
+            v = widget()
+            html += v
+        qs = serializeForm(html)
+        return qs
+
+    @property
     def viewValue(self):
         """Returns the reference view string."""
         current = self._getCurrentValue()
@@ -90,8 +108,8 @@
         target = u''
         current = self._getCurrentValue()
         if current and current.target:
-                intIds = component.getUtility(IIntIds)
-                target = intIds.getId(current.target)
+            intIds = zope.component.getUtility(IIntIds)
+            target = intIds.getId(current.target)
         return target
 
     @property
@@ -103,15 +121,6 @@
         else:
             return u''
 
-    @property
-    def descriptionValue(self):
-        """Returns the reference description."""
-        current = self._getCurrentValue()
-        if current and current.description:
-            return current.description or u''
-        else:
-            return u''
-
     def __call__(self):
         resourcelibrary.need('z3c.reference')
         if self._renderedValueSet():
@@ -127,33 +136,19 @@
             ref = self._emptyReference
         contents = undefined
         targetName = self.name + '.target'
-        viewName = self.name + '.view'
-        titleName = self.name + '.title'
-        descriptionName = self.name + '.description'
+        formDataName = self.name + '.formData'
         intidInput = renderElement(u'input',
-                             type='hidden',
-                             name=targetName,
-                             id=targetName,
-                             value=self.targetValue,
-                             extra=self.extra)
-        viewInput = renderElement(u'input',
-                             type='hidden',
-                             name=viewName,
-                             id=viewName,
-                             value=self.viewValue,
-                             extra=self.extra)
-        titleInput = renderElement(u'input',
-                             type='hidden',
-                             name=titleName,
-                             id=titleName,
-                             value=self.titleValue,
-                             extra=self.extra)
-        descriptionInput = renderElement(u'input',
-                             type='hidden',
-                             name=descriptionName,
-                             id=descriptionName,
-                             value=self.descriptionValue,
-                             extra=self.extra)
+                                   type='hidden',
+                                   name=targetName,
+                                   id=targetName,
+                                   value=self.targetValue,
+                                   extra=self.extra)
+        formDataInput = renderElement(u'input',
+                                      type='hidden',
+                                      name=formDataName,
+                                      id=formDataName,
+                                      value=self.formDataValue,
+                                      extra=self.extra)
         linkTag = renderElement(self.refTag,
                             href = self.referenceEditorURL,
                             name=self.name,
@@ -164,7 +159,7 @@
                             contents=contents,
                             style=self.style,
                             extra=self.extra)
-        return linkTag + viewInput + intidInput + titleInput + descriptionInput
+        return linkTag + intidInput + formDataInput
 
     def _getFormValue(self):
         res = super(ViewReferenceWidget,self)._getFormValue()
@@ -192,10 +187,8 @@
         else:
             ref = ViewReference()
         # form field ids
+        formDataName = self.name + '.formData'
         targetName = self.name + '.target'
-        viewName = self.name + '.view'
-        titleName = self.name + '.title'
-        descriptionName = self.name + '.description'
 
         # get target obj str
         intid = self.request.get(targetName)
@@ -207,24 +200,21 @@
             return self.context.missing_value
         ref.target = obj
 
-        # write view str
-        viewStr = self.request.get(viewName)
-        if viewStr is None:
-            return self.context.missing_value
-        ref.view = unicode(viewStr)
+        # apply the form data
+        formData = self.request.get(formDataName)
+        if not formData:
+            return ref
+        data = cgi.parse_qs(formData)
+        for k, v in data.items():
+            if type(v) is type([]) and len(v)==1:
+                data[k] = v[0]
 
-        # write title str
-        titleStr = self.request.get(titleName)
-        if titleStr is None:
-            return self.context.missing_value
-        ref.title = unicode(titleStr)
-
-        # write description str
-        descriptionStr = self.request.get(descriptionName)
-        if descriptionStr is None:
-            return self.context.missing_value
-        ref.description = unicode(descriptionStr)
-
+        # XXX this is a contract for edit form
+        data['form.actions.apply'] = u''
+        r = TestRequest(form=data)
+        klass = getEditorView(ref.target, self.request,
+                              self.context.settingName).__class__
+        klass(ref, r).update()
         return ref
 
 

Modified: z3c.reference/branches/flash/src/z3c/reference/interfaces.py
===================================================================
--- z3c.reference/branches/flash/src/z3c/reference/interfaces.py	2007-09-07 12:15:50 UTC (rev 79520)
+++ z3c.reference/branches/flash/src/z3c/reference/interfaces.py	2007-09-07 12:20:29 UTC (rev 79521)
@@ -28,16 +28,6 @@
     view. If the target is None, the view name is supposed to be an
     absolute url to an external target"""
 
-    title = zope.schema.Text(
-            title = u'Title',
-            description = u'The title of the reference',
-            )
-
-    description = zope.schema.Text(
-            title = u'Description',
-            description = u'The description of the reference',
-            )
-
     target = zope.schema.Object(
         schema=ILocation,
         title=u'Target Object',



More information about the Checkins mailing list