Accessing portal object trouble

This week a faced a problem trying to access the portal object at the "schema definition scope". All what I was trying to do was reference an object from the portal to provide a link to it from the description of a dexterity field.

Right now i don't have the code anymore, but was something more or less like this:

def get_me_that_link(path):
  portal = api.portal.get()
  object = portal.restrictedTraverse(path)
  return object.absolute_url()


class IMySchema:
  fieldname = zope.schema(
    label=_(u'Field name'),
    description=_(u'<a href="{link}">More info</a>').format(link=get_me_that_link('/fs-mountpoint/plonesite/my-folder/my-basic-page')),
  )

I don't remember if it was exactly like that and if i write correct everything it's the main idea, but all was running ok, until I got an exception that tall me that zope (or plone, I don't remember) couldn't acces to the portal object, i read more about it, and i found that i could be cause running in debug mode, but i was in fg, anyway i tried to run it in normal mode and it was failing anyway.

Your code is not going to work since the calculation is carried out during the startup phase of Zope/Plone and not at runtime. In particular such code would never ever work with multiple portals sharing the same code. To make it short: there is no functionality to calculate information for a dynamic description of a schema field at runtime.

-aj

I know it wouldn't work on diferent portals, but instead of providing a static path i was thinking about read a registry from the portal where the user can specify where is his disclaimer page, so i can link it in the "i accept the terms of use" label.

Which would be the correct solution for a schema defined form?
Create a widget which renders the link? You'll have to create a widget for each kind of field you want to print a link on the label (chechbox, text, ...), which sounds kind of overkill

It is possible (with some monkey patching). I did this for a customer some time ago (no Plone, but Zope3).

We defined a function which generates the description:

def lot_size_description():
    """Generate the description for the 'Lot Size' field.

    The description contains a mapping with the local ``authority_name`` which
    can vary between countries.

    :returns: Description text for the 'Lot Size' field.
    :rtype: string
    """
    loc_data = queryUtility(ILocationData)
    authority_name = loc_data.authority_name
    result = _(
        u'Enter the total area of the property in square meters. (e.g. '
        u'1225.32) Always cross-check data with ${authority_name}.', mapping={
            u'authority_name': authority_name,
        })
    return result

In the schema, no description is used:

class IListingDetails(Interface):
    """Listing Details"""
    lot_size = schema.Decimal(
        min=Decimal('0.01'),
        required=True,
        title=_(u'Total Lot Size'),
    )

We then applied a monkey patch to load the dynamic description:

#: Custom description for 'Total Lot Size'
IListingDetails.get('lot_size').description = listing.lot_size_description()
```

It looks interesting, at which "point of execution"/file did you add the description in the interface's field?
And another question kind of offtopic, i see you use a parameter in the "_" function called "mapping", i guess it just works like the str's "format" method, but does the mapping parameter add some functionality to the i18n translation?

Thanks for your time!

M[quote="Gerard, post:3, topic:4182"]
Which would be the correct solution for a schema defined form?Create a widget which renders the link? You'll have to create a widget for each kind of field you want to print a link on the label (chechbox, text, ...), which sounds kind of overkill
[/quote]

Correct solution...perhaps writing your own widget.
Quick and dirty: some Javascript modifying the DOM.

The patches are loaded at the very end. Please take a look at the Monkey patching docs from Plone.

Yes, it adds a variable to the i18n message which will be replaced on runtime.

Again, my solution is just a quick and dirty hack. Andreas point is totally valid and a custom widget would be the better solution.