Making realations 'automatic when adding '

Lets say you are looking at or editing 'Some Content item (A)'.
The view has a button (link) to ++add++another++content++item.

If you click the link and add the new content item (B), I want the new content item to set/save the related items, so we have a relation A <--> B.

How should I do this?

PS: I am free to make the create link whatever I want, so I can add ?whatever=what&I=want

Customize your AddView of Content Item B and evaluate the Query Paramter, resolve Item A and set the Related Item Behavior on B.

You can just create an object of type B as a child in object of type A. That is a relation of some sort.
You can then use a path query to find objects of type B inside the object of type A.

There's also the option of prefilling an Add view with GET values or POST to an Addview somewhere. You'll have to set allow_prefill_from_GET_request on the form somehow.
Or, add some javascript that will check the URL for ?key=value and set it in the browser.

Hope this helps!

Thanks. Actually, this would be the easies approach, I guess, but in this case I want to add items to the same folder due to some 'automatic numbering of ids'

Set allowed_content_types and filter_content_types on Type A to allow Type B. Also set global_allow=False on Type B.
Now you can add Type B objects only to Type A objects.

Looking at plone.app.content/plone/app/content/namechooser.py at 13e176e17da3ec96140b414760ed59f0bd292d04 · plone/plone.app.content · GitHub it'll probably be enough just to disable the namefromtitle behavior and you'll end up with objects named typeb- + number.

That is what I have done, and it works 'good enough'.

I also know how to pass the UID to the new added content, but I dont know how to 'set it'. I dont know if I am supposed to set the value or if I am supposed to set the widget value or something simlar. I was hoping for something like this

def updateFields(self):
    #related_to =  self.request.get('related_from')
    #Changed field to text just to test
    self.fields['related_item']  = 'ABC'

    super(ActionItemsAddForm, self).updateField

I am not sure if that works with relations, might be wrong, but I think it is difficult to set a 'default' value, and the relationValue is an object that 'links both ways'.

I've described using containment instead of using related items. Unsure why you'd want related items in the first place though.

Any case, add a event handler for IContentAdded, check if its for a Type B object and set the related item fields on the context (Type A).

Or tell you user to add the Type B object, and then select the object by hand.

It is useful when someone tries to delete item A without knowing it has been linked from B

Doesn't containment solve that OOTB?

I did not manage to set the value directly, so instead I set the 'default value' and hide the field/widget in the form. Here is the current code:

from zope.publisher.browser import BrowserView
from plone.dexterity.browser.add import DefaultAddView
from plone.dexterity.browser.add import DefaultAddForm
from plone.dexterity.browser.edit import DefaultEditView
from plone.dexterity.browser.edit import DefaultEditForm
from plone.uuid.interfaces import IUUID
from zope.intid.interfaces import IIntIds
from Products.CMFCore.utils import getToolByName
from z3c.relationfield import RelationValue
from plone import api

from zope.component import getUtility
from z3c.form import interfaces


class ActionItemsAddForm(DefaultAddForm):
    portal_type = "action_items"
    default_fieldset_label = 'Home'

    def __init__(self, context, request):
        super(ActionItemsAddForm, self).__init__(context, request)



    def updateWidgets(self):
        super(ActionItemsAddForm, self).updateWidgets()
        self.widgets['related_item'].mode = interfaces.HIDDEN_MODE



    def updateFields(self):
        super(ActionItemsAddForm, self).updateFields()
        from_uid =  self.request.get('related_from')

        if from_uid:
            came_from  = api.content.get(UID=from_uid)
            initids = getUtility(IIntIds)
            came_from_i = initids.getId(came_from)

            self.fields['related_item'].field.default = RelationValue( came_from_i )

… etc