@types: Distinguishing add and edit contexts
@lukasgraf is already working on this.
Since Jun 21, 2019.
- Dominant language
- Python
- Stars
- 109
- Forks
- 107
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 4
Description
In Plone, both vocabularies as well as default values may be context-sensitive.
An IVocabularyFactory (or an IContextSourceBinder) will be passed a context, as will an IContextAwareDefaultFactory.
Now, depending on whether the user is creating a new object, or editing an existing one, these might get passed different contexts.
In classic Plone, the way this pans out is that when
- adding, the context will be the container to which the object will be added
- editing, the context is the object itself
In other words:
Because the ++add++ ... view is invoked on the container that the object will be added to, a IVocabularyFactory will be passed the parent of the object that is about to be created, and is expected to produce the vocabulary for a particular field for that newly created object, based on information from its parent.
The edit case is much simpler: The object already exists, and the item itself is the context that will be passed to the IVocabularyFactory.
This however leads to ambiguity: The IVocabularyFactory has no frame of reference to determine whether the context it's looking at is the item itself, or the container of the item in question.
It could do container = aq_parent(context) - but that would be wrong during the add form. Or it could do container = context, but that's wrong in the edit form.
This issue only crops up in quite advanced uses of context-aware vocabularies and default factories. In our application, we have so far addressed this by hooking into all the different ways to create content in Plone (plone.api, invokeFactory / createContentInContainer, transmogrifier, REST API, Forms), and adding a IDuringContentCreation marker interface to the request.
That way, the vocabulary factories / default factories that need to know this can do
if IDuringContentCreation.providedBy(request):
# Add form
container = context
else:
# Edit form
container = aq_parent(context)
In plone.restapi we now face the same issue. The @types/:portal_type: endpoint is likely to be used to both render edit as well as add forms. In the most recent version of plone.restapi a field's vocabulary will contain a pointer to a context-sensitive URL to the @vocabulary endpoint for that field's vocabulary. And there we face the same issue:
Is the resource that @vocabulary is invoked on both the target item and the source context? (edit form). Or is it just the source context, and the target item doesn't yet exist? (add form)
The @types endpoint is also a bit awkward to use in the edit form case: It needs to be invoked with a portal_type path parameter by the frontend, even though the context's portal_type is very much known to the backend, and completely unambigous.
We could possibly address both these issues by:
-
Introducing a
@typeendpoint (singular):- Doesn't take a
portal_typeparameter - intended for "edit form" case
- returns only the relevant subset of information for this context
- Doesn't take a
-
Introducing a new marker interface
IDuringContentCreation, that will be applied to the request in the existing@typesendpoint -
Making
@typesexplicitly intended for the "add form" case
I'm mostly thinking out loud here, but I want to jot this down as a basis for discussion for the Beethoven Sprint. I would be interested to hear if anyone else has encountered this issue.
(Obviously using @type in Python could cause some headaches, it's just an example)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.