Closed pbauer closed 10 years ago
You're probably getting an error retrieving the vocabulary data via ajax.
Unfortunately(or fortunately, however you look at it), we're very strict for which vocabularies we allow via ajax requests. We were afraid we might leak data otherwise.
Thank you for bringing this up because the way we do lookups right now is somewhat broken.
In the meantime, I think you should be able to do something like this:
from plone.app.widgets import browser
browser._permissions['mypackage.StaffMembers'] = 'View'
and then your vocabulary should work.
We'll have to think of a better way to do this and still maintain security obviously...
Any ideas anyone else as to a better way to do this?
Also, another problem, we only do permission checks against the root of the site since the getVocabulary
view is only setup to work against the root. This should be moved to work against any context; however, then that opens us up to a potential DOS avenue since the plone.app.vocabularies.Catalog
vocabulary only requires "View" permission... Essentially, we'd be opening up an API to plone that we might not want to.
Is it reasonable to restrict getVocabulary
to logged in users? Then, set default vocabulary access (for all vocabularies) to "Modify portal content" against the real context of the widget (not the always portal root which it is right now). If vocabularies require a different permission, ONLY then do we do the permission check other than "Modify portal content".
Is there any reason the getVocabulary
view should be available to anonymous users? IMO, it should not.
@pbauer also, you should be using the select2 widget instead of related items. Related items is only for selecting content from the catalog--so you really shouldn't be using vocabulary_factory with it.
Would it be feasible to reference a field instead of a vocabulary? Then the field's edit permission could be checked to determine if its vocabulary should be accessible.
We tried to make it simple and generic. For instance, getVocabulary
is also used for live search and eventually /@@search
.
So it wouldn't work for those cases.
I suppose the catalog could be a special case though and all other vocabularies are checked against the field's permissions.
There's no reason relateditemswidget
can't be used for hierarchical
non-content vocabularies. That was the original intention anyway.
True, I get {"error": "Vocabulary lookup not allowed"}
when calling the url in the ajaxvocabulary-parameter. I missed that. With the permission set to "View" I get this:
Module plone.app.widgets.browser, line 157, in __call__
Module inspect, line 813, in getargspec
TypeError: <method-wrapper '__call__' of function object at 0x10bfb0e60> is not a Python function
When using the select2-widget as suggested the existing values in the widgets are only UUIDs and not the titles of the objects (the RelatedItemsWidget shows the title). Where does the RelatedItemsWidget transform these to titles?
The select2-widget actually showed up after I worked around
Module plone.app.widgets.at, line 46, in edit
Module plone.app.widgets.at, line 212, in _widget_args
Module plone.app.widgets.at, line 194, in getWidgetValue
TypeError: sequence item 0: expected string, Acquisition.ImplicitAcquisitionWrapper found
by using the getWidgetValue
-method from the RelatedItemsWidget when the field is a reference-field.
But as you said it did not work right because of the vocabulary.
Okay, I didn't realize that your vocabulary was a vocabulary of objects--I should have known better as I just now noticed you were using ReferenceField. You should go back to using relatedItems. There are two ways you can go:
_permissions
setting).And yes, the integration part of Plone and patterns aren't documented at all. Mostly because it's going to change quite a bit in the following months.
We haven't documented at all how to use your own zope3 vocabulary or how you setup any of the widgets outside their base use-cases we're hitting right now.
So expect some rough edges. Read plone.app.widgets
for hints at how it's all wired up.
Thanks!
I created the pull-request https://github.com/plone/plone.app.widgets/pull/39 to actually use the custom vocabulary. That only kinda works ;-)
ERROR ZServer uncaptured python exception, closing channel
<ZServer.HTTPServer.zhttp_channel connected 127.0.0.1:53898 at 0x10f010128 channel#: 8 requests:>
(<type 'exceptions.ValueError'>:HTTP headers invalid (too long)
(got: 12288 bytes, allowed 8192 bytes
[/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/asyncore.py|read|83]
[/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/asyncore.py|handle_read_event|442]
[/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/asynchat.py|handle_read|170]
[/Users/philip/.cache/buildout/eggs/Zope2-2.13.20-py2.7.egg/ZServer/HTTPServer.py|collect_incoming_data|435])
More issues:
@dextermilo could you take a look if this issues is still valid with all changes you did to related items? @pbauer is documentation better now? -> http://plone.github.io/mockup/dev/#patterns/relateditems
@garbas the documentation does not cover the plone-specifics, but maybe that belongs somewhere else.
We have a open pull-request for plone.app.vocabularies (https://github.com/plone/plone.app.vocabularies/pull/4) that allows you to use the (great) widget with your own vocabularies provided they use the sliceableVocabulary. Here is some example-code for this:
from five import grok
from plone.app.querystring.queryparser import parseFormquery
from plone.app.vocabularies import SlicableVocabulary
from plone.app.widgets import browser
from zope.schema.interfaces import IVocabularyFactory
from zope.schema.vocabulary import SimpleVocabulary
from my.project.interfaces import Hero
class SimpleAndSlicableVocabulary(SimpleVocabulary, SlicableVocabulary):
pass
class HeroesVocabulary(object):
grok.implements(IVocabularyFactory)
def __call__(self, context, query, batch=None):
terms = []
catalog = getToolByName(context, 'portal_catalog')
parsed_query = parseFormquery(context, query['criteria'])
brains = list(catalog(object_provides=IHero.__identifier__,
**parsed_query))
for brain in brains:
terms.append(SimpleVocabulary.createTerm(
brain, str(brain.UID), brain.Title))
return SimpleAndSlicableVocabulary(terms)
grok.global_utility(HeroesVocabulary, name=u"my.project.heroesvocabulary")
browser._permissions['my.project.heroesvocabulary'] = 'View'
The schema might then look like this:
from Products.Archetypes import atapi
from plone.app.widgets import at
MySchema = folder.ATFolderSchema.copy() + atapi.Schema((
atapi.ReferenceField(
'myheroes',
relationship='someones-heroes',
multiValued=True,
storage=atapi.AnnotationStorage(),
vocabulary_factory=u"my.project.heroesvocabulary",
widget=at.RelatedItemsWidget(
label=_(u"Pick your heroes"),
),
)
We also changed the widget (archetypes only for the moment) so you can customize the a different view for vocabularies. The default-view (@@getVocabulary) shows title and path of the objects but sometimes you want something else (like surnames)
widget=at.RelatedItemsWidget(
label=_(u"Heroes again"),
vocabulary_view="@@getSurnameVocabulary",
),
@pbauer
pull request plone.app.vocabularies reviewed and merged. for plone related docs we need to bring back @@demo-widgets which @miohtama started few months ago. i've opened issues #177 so we dont forget
How do I configure the RelatedItemsWidget to let me only choose items from a
vocabulary_factory
? I could not find any pointers.Old code:
This gives me a select-list with names as constructed in mypackage.StaffMembers.
New code:
This code gives me the new RelatedItemsWidget (at-flavor) and my
vocabulary_factory
is ignored. What I want is aselect2
-based widget with only my values as possible reference-targets and without the whole search/browse-stuff.