Metadata-Version: 1.0
Name: z3c.relationfieldui
Version: 0.5
Summary: A widget for z3c.relationfield.
Home-page: UNKNOWN
Author: Martijn Faassen
Author-email: faassen@startifact.com
License: UNKNOWN
Description: *******************
        z3c.relationfieldui
        *******************
        
        This package implements a ``zope.formlib`` compatible widget for
        relations as defined by `z3c.relationfield`_.
        
        .. _`z3c.relationfield`: http://pypi.python.org/pypi/z3c.relationfield
        
        This package does not provide a ``z3c.form`` widget for
        ``z3c.relationfield``, but it is hoped that will eventually be
        developed as well (in another package).
        
        Setup
        =====
        
        In order to demonstrate our widget, we need to first set up a relation
        field (for the details of this see z3c.relationfield's
        documentation)::
        
        >>> from z3c.relationfield import Relation
        >>> from zope.interface import Interface
        >>> class IItem(Interface):
        ...   rel = Relation(title=u"Relation")
        >>> from z3c.relationfield.interfaces import IHasRelations
        >>> from persistent import Persistent
        >>> from zope.interface import implements
        >>> class Item(Persistent):
        ...   implements(IItem, IHasRelations)
        ...   def __init__(self):
        ...     self.rel = None
        >>> from zope.app.component.site import SiteManagerContainer
        >>> from zope.app.container.btree import BTreeContainer
        >>> class TestApp(SiteManagerContainer, BTreeContainer):
        ...   pass
        
        Set up the application with the right utilities::
        
        >>> root = getRootFolder()['root'] = TestApp()
        >>> from zope.app.component.site import LocalSiteManager
        >>> root.setSiteManager(LocalSiteManager(root))
        >>> from zope.app.component.hooks import setSite
        >>> setSite(root)
        >>> from zope.app.intid import IntIds
        >>> from zope.app.intid.interfaces import IIntIds
        >>> root['intids'] = intids = IntIds()
        >>> sm = root.getSiteManager()
        >>> sm.registerUtility(intids, provided=IIntIds)
        >>> from z3c.relationfield import RelationCatalog
        >>> from zc.relation.interfaces import ICatalog
        >>> root['catalog'] = catalog = RelationCatalog()
        >>> sm.registerUtility(catalog, provided=ICatalog)
        
        Items ``a`` and ``b`` with a relation from ``b`` to ``a``::
        
        >>> root['a'] = Item()
        >>> from z3c.relationfield import RelationValue
        >>> b = Item()
        >>> from zope import component
        >>> from zope.app.intid.interfaces import IIntIds
        >>> intids = component.getUtility(IIntIds)
        >>> a_id = intids.getId(root['a'])
        >>> b.rel = RelationValue(a_id)
        >>> root['b'] = b
        
        We also need to set up a utility that knows how to generate an object
        path for a given object, and back::
        
        >>> import grokcore.component as grok
        >>> from z3c.objpath.interfaces import IObjectPath
        >>> class ObjectPath(grok.GlobalUtility):
        ...   grok.provides(IObjectPath)
        ...   def path(self, obj):
        ...       return obj.__name__
        ...   def resolve(self, path):
        ...       try:
        ...           return root[path]
        ...       except KeyError:
        ...           raise ValueError("Cannot resolve: %s" % path)
        >>> grok.testing.grok_component('ObjectPath', ObjectPath)
        True
        
        Let's also set up a broken relation::
        
        >>> d = root['d'] = Item()
        >>> d_id = intids.getId(root['d'])
        >>> c = Item()
        >>> c.rel = RelationValue(d_id)
        >>> root['c'] = c
        >>> del root['d']
        >>> root['c'].rel.to_object is None
        True
        >>> root['c'].rel.isBroken()
        True
        
        The relation widget
        ===================
        
        The relation widget can be looked up for a relation field. The widget
        will render with a button that can be used to set the
        relation. Pressing this button will show a pop up window. The URL
        implementing the popup window is defined on a special view that needs
        to be available on the context object (that the relation is defined
        on). This view must be named "explorerurl". We'll provide one here::
        
        >>> from zope.interface import Interface
        >>> import grokcore.view
        >>> class ExplorerUrl(grokcore.view.View):
        ...   grok.context(Interface)
        ...   def render(self):
        ...      return 'http://grok.zope.org'
        
        Now we can Grok the view::
        
        >>> grok.testing.grok_component('ExplorerUrl', ExplorerUrl)
        True
        
        Let's take a look at the relation widget now::
        
        >>> from zope.publisher.browser import TestRequest
        >>> from z3c.relationfieldui import RelationWidget
        >>> request = TestRequest()
        >>> field = IItem['rel']
        >>> bound = field.bind(root['b'])
        >>> widget = RelationWidget(bound, request)
        >>> widget.setRenderedValue(bound.get(root['b']))
        >>> print widget()
        <input class="textType" id="field.rel" name="field.rel" size="20" type="text" value="a"  /><input class="buttonType" onclick="Z3C.relation.popup(this.previousSibling, 'http://grok.zope.org?from_attribute=rel&amp;from_path=b')" type="button" value="get relation" />
        
        Let's also try it with the broken relation::
        
        >>> bound = field.bind(root['c'])
        >>> widget = RelationWidget(bound, request)
        >>> widget.setRenderedValue(bound.get(root['c']))
        
        When we render the widget, the value is still correct (even though
        it's broken)::
        
        >>> 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
        =======================
        
        The display widget for relation will render a URL to the object it relates
        to. What this URL will be exactly can be controlled by defining a view
        on the object called "relationurl". Without such a view, the display
        widget will link directly to the object::
        
        >>> from z3c.relationfieldui import RelationDisplayWidget
        >>> bound = field.bind(root['b'])
        >>> widget = RelationDisplayWidget(bound, request)
        >>> widget.setRenderedValue(bound.get(root['b']))
        
        The widget will point to the plain URL of ``rel``'s ``to_object``::
        
        >>> print widget()
        <a href="http://127.0.0.1/root/a">a</a>
        
        Now we register a special ``relationurl`` view::
        
        >>> class RelationUrl(grokcore.view.View):
        ...   grok.context(Interface)
        ...   def render(self):
        ...      return self.url('edit')
        >>> grok.testing.grok_component('RelationUrl', RelationUrl)
        True
        
        We should now see a link postfixed with ``/edit``::
        
        >>> print widget()
        <a href="http://127.0.0.1/root/a/edit">a</a>
        
        When the relation is broken, it will still display, but as broken::
        
        >>> bound = field.bind(root['c'])
        >>> widget = RelationDisplayWidget(bound, request)
        >>> widget.setRenderedValue(bound.get(root['c']))
        >>> print widget()
        Broken relation to: d
        
        CHANGES
        *******
        
        0.5 (2009-02-10)
        ================
        
        * 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)
        ================
        
        * Use improved ``z3c.relationfield`` to better handle broken
        relations.  Broken relations are now accepted by the UI but will be
        stored as broken.
        
        0.3 (2009-01-16)
        ================
        
        * Pass along ``from_attribute`` and ``from_path`` URL parameters to
        explorer_url.
        
        0.2 (2009-01-08)
        ================
        
        * Update the value of the input field using ``.value`` instead of
        using ``setAttribute('value', ...)``. The latter did not update
        dynamically updated input fields, and the former does.
        
        * ``z3c.relationfield`` does not use ``IRelationInfo`` anymore and
        instead exposes ``create_relation``. Use this instead.
        
        0.1.1 (2008-12-10)
        ==================
        
        * Small internet Explorer compatibility tweaks.
        
        0.1 (2008-12-05)
        ================
        
        * Initial public release.
        
        Download
        ********
        
Platform: UNKNOWN
