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
