Vincent
Vincent

Reputation: 630

Plone and Dexterity: default values for "relation" field

In one of my Plone sites, I have a few dexterity models that I use to generate letters. The models are: "Model" (the base content of the letter), "Contact" (that contains the contact information, such as name, address etc) and "Merge" (which is a Model object rendered, in which we substitute some parts of the model with the recipients information). The schema of the "Merge" object is the following:

class IMergeSchema(form.Schema):
    """
    """
    title = schema.TextLine(
        title=_p(u"Title"),
        )

    form.widget(text='plone.app.z3cform.wysiwyg.WysiwygFieldWidget')
    text = schema.Text(
        title=_p(u"Text"),
        required=False,
        )

    form.widget(recipients=MultiContentTreeFieldWidget)
    recipients = schema.List(
        title=_('label_recipients',
                 default='Recipients'),
        value_type=schema.Choice(
            title=_('label_recipients',
                      default='Recipients'),
            # Note that when you change the source, a plone.reload is
            # not enough, as the source gets initialized on startup.
            source=UUIDSourceBinder(portal_type='Contact')),
        )

    form.widget(model=ContentTreeFieldWidget)
    form.mode(model='display')
    model = schema.Choice(
        title=_('label_model',
                  default='Model'),
        source=UUIDSourceBinder(portal_type='Model'),
        )

When creating a new "Merge" object, I want to have the "recipients" fields be preset with all contacts available in the folder where the new object is created. I followed Martin Aspelli's guide to add a default value for a field: http://plone.org/products/dexterity/documentation/manual/developer-manual/reference/default-value-validator-adaptors

It works fine for text input fields, but I can't have it working for the "recipients" field. The method to generate the default values is the following (with some debug info with ugly print, but they'll be removed later ;) ):

@form.default_value(field=IMergeSchema['recipients'])
def all_recipients(data):
    contacts =  [x for x in data.context.contentValues()
                 if IContact.providedBy(x)]
    paths =  [u'/'.join(c.getPhysicalPath()) for c in contacts]
    uids = [IUUID(c, None) for c in contacts]

    print 'Contacts: %s' % contacts
    print 'Paths: %s' % paths
    print 'UIDs: %s' % uids

    return paths

I tried to return the objects directly, their relative path (in the add view, when accessing "self.widgets['recipients'].value", I get this type of data) their UIDs but none of the solution as any effect.

I also tried to return tuples instead of lists or even generators, but still no effect at all.

The method is called for sure, as I see traces in the instance log.

Upvotes: 5

Views: 1327

Answers (1)

marcosfromero
marcosfromero

Reputation: 2853

I think you need to get the "int_id" of the related content. That's how dexterity relation fields store relation info::

from zope.component import getUtility
from zope.intid.interfaces import IIntIds

@form.default_value(field=IMergeSchema['recipients'])
def all_recipients(data):
    contacts =  [x for x in data.context.contentValues()
                 if IContact.providedBy(x)]
    intids = getUtility(IIntIds)
    # The following gets the int_id of the object and turns it into
    # RelationValue
    values = [RelationValue(intids.getId(c)) for c in contacts]

    print 'Contacts: %s' % contacts
    print 'Values: %s' % values

    return values

Upvotes: 3

Related Questions