[Checkins] SVN: z3c.relationfieldui/trunk/ Support for RelationChoice fields.

Martijn Faassen faassen at infrae.com
Tue Feb 10 14:51:52 EST 2009


Log message for revision 96414:
  Support for RelationChoice fields.
  

Changed:
  U   z3c.relationfieldui/trunk/CHANGES.txt
  U   z3c.relationfieldui/trunk/buildout.cfg
  U   z3c.relationfieldui/trunk/setup.py
  U   z3c.relationfieldui/trunk/src/z3c/relationfieldui/README.txt
  U   z3c.relationfieldui/trunk/src/z3c/relationfieldui/__init__.py
  U   z3c.relationfieldui/trunk/src/z3c/relationfieldui/configure.zcml
  U   z3c.relationfieldui/trunk/src/z3c/relationfieldui/interfaces.py
  A   z3c.relationfieldui/trunk/src/z3c/relationfieldui/source.py
  U   z3c.relationfieldui/trunk/src/z3c/relationfieldui/widget.py

-=-
Modified: z3c.relationfieldui/trunk/CHANGES.txt
===================================================================
--- z3c.relationfieldui/trunk/CHANGES.txt	2009-02-10 19:51:08 UTC (rev 96413)
+++ z3c.relationfieldui/trunk/CHANGES.txt	2009-02-10 19:51:51 UTC (rev 96414)
@@ -4,7 +4,10 @@
 0.5 (unreleased)
 ================
 
-* ...
+* Add support for ``RelationChoice`` field. To create a relation field that
+  uses a drop-down list to select the relation target, implement a
+  ``RelationSourceFactory`` (implement the ``getTargets`` method), and
+  pass it as a source to ``RelationChoice``.
 
 0.4 (2009-01-20)
 ================

Modified: z3c.relationfieldui/trunk/buildout.cfg
===================================================================
--- z3c.relationfieldui/trunk/buildout.cfg	2009-02-10 19:51:08 UTC (rev 96413)
+++ z3c.relationfieldui/trunk/buildout.cfg	2009-02-10 19:51:51 UTC (rev 96414)
@@ -8,6 +8,11 @@
 [versions]
 lxml = 2.0.9
 zope.testing = 3.6.0
+# 0.4.0 introduces dependency on zope.browser, but without
+# a newer zope.app.form that will lead to problems. for now lock them
+# down
+zc.sourcefactory = 0.3.4
+zope.app.form = 3.4.1
 
 [test]
 recipe = zc.recipe.testrunner

Modified: z3c.relationfieldui/trunk/setup.py
===================================================================
--- z3c.relationfieldui/trunk/setup.py	2009-02-10 19:51:08 UTC (rev 96413)
+++ z3c.relationfieldui/trunk/setup.py	2009-02-10 19:51:51 UTC (rev 96414)
@@ -30,8 +30,9 @@
     zip_safe=False,
     install_requires=[
         'setuptools',
-        'z3c.relationfield >= 0.3.1',
+        'z3c.relationfield >= 0.4',
         'z3c.schema2xml >= 1.0',
+        'zc.sourcefactory',
         'grokcore.component',
         'grokcore.view',
         'hurry.resource',

Modified: z3c.relationfieldui/trunk/src/z3c/relationfieldui/README.txt
===================================================================
--- z3c.relationfieldui/trunk/src/z3c/relationfieldui/README.txt	2009-02-10 19:51:08 UTC (rev 96413)
+++ z3c.relationfieldui/trunk/src/z3c/relationfieldui/README.txt	2009-02-10 19:51:51 UTC (rev 96414)
@@ -139,6 +139,81 @@
   >>> print widget()
   <input class="textType" id="field.rel" name="field.rel" size="20" type="text" value="d"  /><input class="buttonType" onclick="Z3C.relation.popup(this.previousSibling, 'http://grok.zope.org?from_attribute=rel&amp;from_path=c')" type="button" value="get relation" />
 
+Relation Choice
+===============
+
+Let's examine the ``RelationChoice`` field from ``z3c.relationfield``. We
+need to provide a source of possible relations for it, and we can do this
+using the ``RelationSourceFactory``::
+
+  >>> from z3c.relationfieldui import RelationSourceFactory
+  >>> class MyRelationSourceFactory(RelationSourceFactory):
+  ...    def getTargets(self):
+  ...        return [root['a'], root['b'], root['c']]
+
+In the source, we simply return an iterable of objects that are
+possible relation targets.
+
+Let's now create an object that makes use of this source::
+
+  >>> from z3c.relationfield import RelationChoice
+  >>> class IItemChoice(Interface):
+  ...   rel = RelationChoice(title=u"Relation", required=False,
+  ...                        source=MyRelationSourceFactory())
+
+We can now take a look at the widget, using ``ChoiceInputWidget``::
+
+  >>> from zope.app.form.browser import ChoiceInputWidget
+
+  >>> class ItemChoice(Persistent):
+  ...   implements(IItemChoice, IHasRelations)
+  ...   def __init__(self):
+  ...     self.rel = None
+
+  >>> root['choice_a'] = ItemChoice()
+  >>> field = IItemChoice['rel']
+  >>> bound = field.bind(root['choice_a'])
+  >>> widget = ChoiceInputWidget(bound, request)
+
+Let's first render the widget without a particular rendered value set::
+
+  >>> print widget()
+  <div>
+  <div class="value">
+  <select id="field.rel" name="field.rel" size="1" >
+  <option selected="selected" value="">(no value)</option>
+  <option value="a">a</option>
+  <option value="b">b</option>
+  <option value="c">c</option>
+  </select>
+  </div>
+  <input name="field.rel-empty-marker" type="hidden" value="1" />
+  </div>
+
+Let's try it again with a value set as a relation to ``a``::
+
+  >>> choice_b = ItemChoice()
+  >>> choice_b.rel = RelationValue(a_id)
+  >>> root['choice_b'] = choice_b
+  >>> bound = field.bind(root['choice_b'])
+  >>> widget = ChoiceInputWidget(bound, request)
+  >>> widget.setRenderedValue(bound.get(root['b']))
+
+When we look at the widget we see that this relation is indeed selected::
+
+  >>> print widget()
+  <div>
+  <div class="value">
+  <select id="field.rel" name="field.rel" size="1" >
+  <option value="">(no value)</option>
+  <option selected="selected" value="a">a</option>
+  <option value="b">b</option>
+  <option value="c">c</option>
+  </select>
+  </div>
+  <input name="field.rel-empty-marker" type="hidden" value="1" />
+  </div>
+
 Relation display widget
 =======================
 

Modified: z3c.relationfieldui/trunk/src/z3c/relationfieldui/__init__.py
===================================================================
--- z3c.relationfieldui/trunk/src/z3c/relationfieldui/__init__.py	2009-02-10 19:51:08 UTC (rev 96413)
+++ z3c.relationfieldui/trunk/src/z3c/relationfieldui/__init__.py	2009-02-10 19:51:51 UTC (rev 96414)
@@ -1 +1,2 @@
 from z3c.relationfieldui.widget import RelationWidget, RelationDisplayWidget
+from z3c.relationfieldui.source import RelationSourceFactory

Modified: z3c.relationfieldui/trunk/src/z3c/relationfieldui/configure.zcml
===================================================================
--- z3c.relationfieldui/trunk/src/z3c/relationfieldui/configure.zcml	2009-02-10 19:51:08 UTC (rev 96413)
+++ z3c.relationfieldui/trunk/src/z3c/relationfieldui/configure.zcml	2009-02-10 19:51:51 UTC (rev 96414)
@@ -7,6 +7,7 @@
   <include package="grokcore.view" file="meta.zcml" />
 
   <include package="hurry.zoperesource" />
+  <include package="zc.sourcefactory" />
   <include package="z3c.relationfield" />
 
   <grok:grok package="."/>

Modified: z3c.relationfieldui/trunk/src/z3c/relationfieldui/interfaces.py
===================================================================
--- z3c.relationfieldui/trunk/src/z3c/relationfieldui/interfaces.py	2009-02-10 19:51:08 UTC (rev 96413)
+++ z3c.relationfieldui/trunk/src/z3c/relationfieldui/interfaces.py	2009-02-10 19:51:51 UTC (rev 96414)
@@ -1,2 +1,7 @@
-#
+from zc.sourcefactory.interfaces import IValuePolicy
 
+class IRelationValuePolicy(IValuePolicy):    
+    def getTargets():
+        """Return an iterable of objects that are potential relation targets.
+        """
+

Added: z3c.relationfieldui/trunk/src/z3c/relationfieldui/source.py
===================================================================
--- z3c.relationfieldui/trunk/src/z3c/relationfieldui/source.py	                        (rev 0)
+++ z3c.relationfieldui/trunk/src/z3c/relationfieldui/source.py	2009-02-10 19:51:51 UTC (rev 96414)
@@ -0,0 +1,49 @@
+from zope import component
+from zope.app.intid.interfaces import IIntIds
+from zope.interface import implements
+from zc.sourcefactory.interfaces import ITokenPolicy, ISourcePolicy
+from zc.sourcefactory.policies import BasicTermPolicy
+from zc.sourcefactory.factories import BasicSourceFactory
+from z3c.objpath.interfaces import IObjectPath
+from z3c.relationfield import RelationValue
+
+from z3c.relationfieldui.interfaces import IRelationValuePolicy
+        
+class RelationValuePolicy(object):
+    implements(IRelationValuePolicy)
+    
+    def getTargets(self):
+        raise NotImplementedError
+
+    def getValues(self):
+        getId = component.getUtility(IIntIds).getId
+        return [RelationValue(getId(target)) for target in self.getTargets()]
+
+    def filterValue(self, value):
+        return True
+
+class RelationTokenPolicy(object):
+    implements(ITokenPolicy)
+    
+    def getToken(self, value):
+        return value.to_path    
+
+    def getValue(self, source, token):
+        resolve = component.getUtility(IObjectPath).resolve
+        try:
+            obj = resolve(token)
+        except ValueError:
+            result = RelationValue(None)
+            result.broken(token)
+            return result
+        getId = component.getUtility(IIntIds).getId
+        return RelationValue(getId(obj))
+
+class RelationTermPolicy(BasicTermPolicy):
+    def getTitle(self, value):
+        return value.to_path
+
+class RelationSourceFactory(BasicSourceFactory,
+                            RelationValuePolicy, RelationTokenPolicy,
+                            RelationTermPolicy):
+    implements(ISourcePolicy)

Modified: z3c.relationfieldui/trunk/src/z3c/relationfieldui/widget.py
===================================================================
--- z3c.relationfieldui/trunk/src/z3c/relationfieldui/widget.py	2009-02-10 19:51:08 UTC (rev 96413)
+++ z3c.relationfieldui/trunk/src/z3c/relationfieldui/widget.py	2009-02-10 19:51:51 UTC (rev 96414)
@@ -7,12 +7,14 @@
 from zope import component
 from zope.component.interfaces import ComponentLookupError
 from zope.app.form.browser.widget import renderElement
+from zope.app.form.browser.interfaces import ISimpleInputWidget
+from zope.app.form.browser import ChoiceInputWidget
 from zope.traversing.browser import absoluteURL
 
 from z3c.objpath.interfaces import IObjectPath
 from hurry.resource import Library, ResourceInclusion
 
-from z3c.relationfield.schema import IRelation
+from z3c.relationfield.schema import IRelation, IRelationChoice
 from z3c.relationfield import create_relation
 
 relation_lib = Library('z3c.relationfieldui')
@@ -49,6 +51,11 @@
             return ''
         return value.to_path
 
+ at grok.adapter(IRelationChoice, IBrowserRequest)
+ at grok.implementer(ISimpleInputWidget)
+def RelationChoiceInputWidget(field, request):
+    return ChoiceInputWidget(field, request)
+
 class RelationDisplayWidget(grok.MultiAdapter, DisplayWidget):
     grok.adapts(IRelation, IBrowserRequest)
     grok.provides(IDisplayWidget)



More information about the Checkins mailing list