Plone 5: Dexterity content types do not provide IContentType

161 views Asked by At

I created a Dexterity content type and defined a simple schema:

....
....
class IMyType(model.Schema):
    myField = schema.TextLine(
            title=_(u"My Field:"),
        )
....
....

Under Plone 4.3, Dexterity content types provide IContentType. However, under Plone 5.0.6 it seems that Dexterity content types do not provide IContentType and as such queryContentType(IMyType) returns 'None'.

Also:

IContentType.providedBy(IMyType)

returns 'False'.

Trying the same with a default content type also gives the same negative results.

Obviously, for my custom content type this can be resolved as follows:

....
from zope.interface import alsoProvides
....
class IMyType(model.Schema):
    myField = schema.TextLine(
            title=_(u"My Field:"),
        )

alsoProvides(IMyType, IContentType)

queryContentType(IMyType) now returns the expected schema and IContentType.providedBy(IMyType) returns 'True'.

However, I would expect all Dexterity content types automatically providing IContentType. Am I expecting too much, or is this a bug in plone.dexterity and/or Plone 5.x ?

2

There are 2 answers

0
sdupton On

plone.dexterity 2.0+ only has a "soft dependency" on zope.app.content, and your build does not have it installed. Your add-on can have the desired interface provided on content type interfaces if you add zope.app.content to your setup.py install_requires and pin a version (3.5.1) in your buildout. Should you do this, all your content type schema/interface classes will provide IContentType.

0
Eric R. On

Sorry for my late reply. The reason why I need this, is because I have created a CSV/PDF export utility, where a user can export objects per their requirements. For that reason I need to acquire the schema of a content type to create the header row of the CSV file and populate the table. In my Plone 4.3 site I did this by means of:

from zope.app.content import queryContentType
from zope.schema import getFieldsInOrder
....

schema = queryContentType(obj)
fields = getFieldNamesInOrder(schema)
# Write header
headerrow=[]
    for field in fields:
        headerrow.append(field)
    writer.writerow(headerrow,)
        fields = getFieldNamesInOrder(schema)

    # Write body
    for item in results:
        obj = item.getObject()
        newrow=[]
        for field in fields:
            value = getattr(obj, field)

            ## some conditioning stuff here....
            if type(value) not in (str, bool, list, unicode, datetime.date, datetime.datetime):
                value = ''
            if type(value) is datetime.date:
                value = str(value)
            if type(value) is datetime.datetime:
                value = str(value)
                value = value[:-7]
            if type(value) is bool:
                value = str(value)
            if type(value) is list:
                newvalue = ''
                for item in value:
                    newvalue = newvalue + str(item) + ';'
                value = newvalue
            if value is None:
                value = ''

            valuestring = value.encode('utf-8')
            newrow.append(valuestring)
        writer.writerow(newrow,)
....

This only works if the object provides IContentType and thus zope.app.content is required. Please see https://docs.plone.org/external/plone.app.dexterity/docs/reference/manipulating-content-objects.html#object-introspection

It may be helpful to have the documentation updated, indicating that zope.app.content is no longer shipped out of the box. If there is a more up-to-date method to obtain an object's schema that would not require zope.app.content, please let me know!

Cheers,

Eric