[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&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