Is there a way to extend Plone Dexterity's INameFromTitle behavior?
Asked Answered
R

2

6

The project I am working on uses Plone's awesome Dexterity plugin. A couple of my custom content types have very specific names that must be computed. The way I had originally accomplished this before was by adding plone.app.content.interfaces.INameFromTitle as a behavior in the object's generic setup entry, per the manual's directions:

<?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 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 that suggested in this blog post:

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

Unfortunately, this method stopped working after plone.app.dexterity beta and now my content items don't have their names assigned properly.

Would anyone happen to know how to extend Dexterity's INameFromTitle behavior for very specific naming use-cases?

Your help is much appreciated, thanks!

Rosalba answered 1/11, 2011 at 23:48 Comment(0)
D
4

You could 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 generally prefer defining my adapters using ZCML; in configure.zcml

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

but you could probably also use a grok.global_adapter.

Dennis answered 5/1, 2012 at 9:39 Comment(0)
L
3

I did it with a behavior, by 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 INameFromTitle behavior in profiles/types/your.contenttype.xml.

Voila. This integrates very well and shows a proper title in the default view and navigation. Removing context.setTitle(title) from the adapter would just leave us with a proper id, but no title set.

This does not change the title autocratically after editing. I had, so far, no success with overriding the klass property of my content types, as often suggested.

If you define the title attribute in your schema, like:

class IBike(form.Schema):
    """A bike
    """

    title = schema.TextLine(
        title = _(u'Title'),
        required = False,
    )

you can easily change the title later. Hiding the title field in the addForm should be done, to avoid misunderstandings.

Lepidosiren answered 13/10, 2012 at 17:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.