Is there a way to extend the behavior of Plone Dexterity INameFromTitle?

The project I'm working on uses the Plone awesome Dexterity plugin. Several of my custom content types have very specific names that need to be calculated. The way I did this before was to add plone.app.content.interfaces.INameFromTitle as the behavior in the object’s general purpose record as directed by the manual:

<?xml version="1.0"?> <object name="avrc.aeh.cycle" meta_type="Dexterity FTI"> ... <property name="schema">myproject.mytype.IMyType</property> <property name="klass">plone.dexterity.content.Item</property> ... <property name="behaviors"> <element value="plone.app.content.interfaces.INameFromTitle" /> </property> ... </object> 

Then I created an adapter that would provide an INameFromTitle:

 from five import grok from zope.interface import Interface import zope.schema from plone.app.content.interfaces import INameFromTitle class IMyType(Interface): foo = zope.schema.TextLine( title=u'Foo' ) class NameForMyType(grok.Adapter): grok.context(IMyType) grok.provides(INameFromTitle) @property def title(self): return u'Custom Title %s' % self.context.foo 

This method is very similar to the one suggested in this blog post:

http://davidjb.com/blog/2010/04/plone-and-dexterity-working-with-computed-fields

Unfortunately, this method stopped working after beta testing plone.app.dexterity, and now my content elements do not have proper names assigned to them.

Can anyone learn how to extend Dexterity INameFromTitle behavior for very specific use cases for names?

Your help is much appreciated, thanks!

+7
source share
2 answers

You can try the following.

in interfaces.py

 from plone.app.content.interfaces import INameFromTitle class INameForMyType(INameFromTitle): def title(): """Return a custom title""" 

in behaviors.py

 from myproject.mytype.interfaces import INameForMyType class NameForMyType(object): implements(INameForMyType) def __init__(self, context): self.context = context @property def title(self): return u"Custom Title %s" % self.context.foo 

I usually prefer to define my adapters using ZCML; in configure.zcml

 <adapter for="myproject.mytype.IMyType" factory=".behaviors.NameForMyType" provides=".behaviors.INameForMyType" /> 

but you can probably also use grok.global_adapter.

+4
source

I did this with behavior adapting to INameFromTitle

in behaviors.py

 class INameFromBrandAndModel(Interface): """ Interface to adapt to INameFromTitle """ class NameFromBrandAndModel(object): """ Adapter to INameFromTitle """ implements(INameFromTitle) adapts(INameFromBrandAndModel) def __init__(self, context): pass def __new__(cls, context): brand = context.brand model = context.modeltype title = u'%s %s' % (brand,model) inst = super(NameFromBrandAndModel, cls).__new__(cls) inst.title = title context.setTitle(title) return inst 

in behaviors.zcml or configure.zcml

 <plone:behavior title="Name from brand and model" description="generates a name from brand and model attributes" for="plone.dexterity.interfaces.IDexterityContent" provides=".behavios.INameFromBrandAndModel" /> <adapter factory=".behaviors.NameFromBrandAndModel" /> 

Then disable the INameFromTitle behavior in profiles/types/your.contenttype.xml .

Voila. It integrates very well and shows the correct title in the default view and navigation. Removing context.setTitle(title) from the adapter will simply leave us with the correct identifier, but the title will not be set.

This will not change the name automatically after editing. So far I have not had time to override the klass property for my content types, as is often suggested.

If you define the title attribute in your schema, for example:

 class IBike(form.Schema): """A bike """ title = schema.TextLine( title = _(u'Title'), required = False, ) 

You can easily change the name later. Hide the header field in addForm should be done to avoid misunderstandings.

+3
source

All Articles