This is a pre-production deployment of Warehouse, however changes made here WILL affect the production instance of PyPI.
Latest Version Dependencies status unknown Test status unknown Test coverage unknown
Project Description

This package implements a zope.formlib compatible widget for relations as defined by 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

Release History

Release History

0.5

This version

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.4

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.3

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.2

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.1.1

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.1

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

Download Files

Download Files

TODO: Brief introduction on what you do with files - including link to relevant help section.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
z3c.relationfieldui-0.5.tar.gz (9.8 kB) Copy SHA256 Checksum SHA256 Source Feb 10, 2009

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting