- term: entry in a vocabulary
- token: ASCII string which is passed when form is submited
- value: actuall value which would be stored in object
- title: representational string (unicode)
class IPerson(form.Schema):
...
favorite_colors = schema.Set(
title=u"Favorite colors",
value_type=schema.Choice(values=['red', 'green', 'blue', 'yellow'])
country = schema.Choice(
title=u"Country",
values=['Slovenia', 'Spain', 'Portugal', 'France'])
from zope.schema.interfaces import IContextSourceBinder
from zope.schema.vocabulary import SimpleVocabulary
grok.provider(IContextSourceBinder)
def countries_list(context):
terms = []
for term in ['Slovenia', 'Spain', 'Portugal', 'France']:
terms.append(SimpleVocabulary.createTerm(term, term, term))
return SimpleVocabulary(terms)
class IPerson(form.Schema):
...
country = schema.Choice(
title=u"Country",
source=countries_list)
... or ...
class CountriesList(object):
grok.implements(IContextSourceBinder)
def __init__(self, continent):
self.continent = continent
def __call__(self, context):
countries = dict(
europe=['Slovenia', 'Spain', 'Portugal', 'France'],
south_america=['Argentina', 'Brasil', 'Chile'], )
terms = []
for term in countries[self.continent]:
terms.append(SimpleVocabulary.createTerm(term, term, term))
return SimpleVocabulary(terms)
class IPerson(form.Schema):
...
country = schema.Choice(
title=u"Country",
source=CountriesList('south_america'))
from zope.schema.interfaces import IVocabularyFactory
class CountriesList(object)
grok.implements(IVocabularyFactory)
def __call__(self, context):
terms = []
for term in ['Slovenia', 'Spain', 'Portugal', 'France']:
terms.append(SimpleVocabulary.createTerm(term, term, term))
return SimpleVocabulary(terms)
grok.global_utility(CountriesList, name=u"countries_list")
class IPerson(form.Schema):
...
country = schema.Choice(
title=u"Country",
vocabulary=u"countries_list")
Imagine you have big vocabularies with a lot of relations. I’m talking +10.000 terms with +30.000 relations. So this would be perfect use case to use collective.vdexvocabulary. Also there are other stuff which I didn’t found in other vocabulary packages for Plone/Zope:
- i18n support (as it is defined in IMS VDEX)
- proper order also with unicode charecters (if zope.ucol is installed)
- easy registration using zcml
- relations as it specified in IMS VDEX standard
In your configure.zcml add
<configure
...
xmlns:vdex="http://namespaces.zope.org/vdex"
...>
<include package="collective.vdexvocabulary" file="meta.zcml" />
<include package="collective.vdexvocabulary" />
And to register a vdex vocabulary simply add line bellow pointing to file containing vdex vocabulary
<configure
...
xmlns:vdex="http://namespaces.zope.org/vdex"
...>
<vdex:vocabulary file="path-to/very-interesting.xml" />
To make registration of vocabularies even easier you can also register several vocabularies and just point to directory
<configure
...
xmlns:vdex="http://namespaces.zope.org/vdex"
...>
<vdex:vocabulary directory="path-to/my-vdex-vocabularies" />
vdex files in path-to/my-vdex-vocabularies directory should have ending .vdex to be recognized by vdex:vocabulary ZCML directive.
Example of car manufacturers list (car_manufacturers.vdex).
<?xml version="1.0" encoding="utf-8"?>
<vdex xmlns="http://www.imsglobal.org/xsd/imsvdex_v1p0"
orderSignificant="false" language="en">
<vocabIdentifier>your.package.car_manufacturers</vocabIdentifier>
<term>
<termIdentifier>ford</termIdentifier>
<caption>
<langstring language="en">Ford</langstring>
<langstring language="es">Una miedra de coche</langstring>
</caption>
</term>
<term>
<termIdentifier>bmw</termIdentifier>
<caption>
<langstring language="en">BMW</langstring>
<langstring language="es">Be-eMe-uWe, mierda</langstring>
</caption>
</term>
<relationship>
<sourceTerm>bmw</sourceTerm>
<targetTerm vocabIdentifier="your.package.car_models">very-special-bmw-model</targetTerm>
<relationshipType source="http://www.imsglobal.org/vocabularies/iso2788_relations.xml">NT</relationshipType>
</relationship>
...
</vdex>
List of car models (car_models.vdex).
<?xml version="1.0" encoding="utf-8"?>
<vdex xmlns="http://www.imsglobal.org/xsd/imsvdex_v1p0"
orderSignificant="false" language="en">
<vocabIdentifier>your.package.car_models</vocabIdentifier>
<term>
<termIdentifier>very-special-bmw-model</termIdentifier>
<caption>
<langstring language="en">Very special BMW model</langstring>
<langstring language="es">Un modelo de Be-eMe-uWe</langstring>
</caption>
</term>
<relationship>
<sourceTerm>very-special-bmw-model</sourceTerm>
<targetTerm vocabIdentifier="your.package.car_manufacturers">bmw</targetTerm>
<relationshipType source="http://www.imsglobal.org/vocabularies/iso2788_relations.xml">BT</relationshipType>
</relationship>
...
</vdex>
Relations are defined by ISO2788.
To get listing of BMW car models from above VDEX example you have to
from zope.schema.vocabulary import getVocabularyRegistry
vr = getVocabularyRegistry()
car_manufacturers = vr.get(self.context, 'your.package.car_manufacturers')
car_models = vr.get(self.context, 'your.package.car_models')
bmw = car_manufacturers.getTerm('bmw')
bmw_car_models = bmw.related.get('NT', [])
Like elephants don’t forget anything, so does not collective.elephantvocabulary. It provides a wrapper around for existing zope.schema vocabularies and make them not forget anything.
Examples:
from collective.elephantvocabulary import wrap_vocabulary
class IPerson(form.Schema):
...
# countries_list -> ['Slovenia', 'Spain', 'Portugal', 'France']
country1 = schema.Choice(
title=u"Country",
vocabulary=wrap_vocabulary(countries_list, hidden_terms=['Slovenia']))
# [Spain', 'Portugal', 'France']
country2 = schema.Choice(
title=u"Country",
vocabulary=wrap_vocabulary(countries_list,
visible_terms=['Slovenia', 'Portugal']))
# ['Slovenia', 'Portugal']
country3 = schema.Choice(
title=u"Country",
vocabulary=wrap_vocabulary(countries_list, hidden_terms=['Slovenia'],
visible_terms=['Slovenia', 'Spain', 'Portugal']))
# ['Spain', 'Portugal']
country4 = schema.Choice(
title=u"Country",
vocabulary=wrap_vocabulary(u'countries_list',
hidden_terms=['Slovenia', 'Spain']))
# ['Portugal', 'France']
country5 = schema.Choice(
title=u"Country",
vocabulary=wrap_vocabulary(u'countries_list',
hidden_terms_from_registry=u"example.hidden_countries"))