How to set the 'exclude_from_nav' in plone 5?

in plone 2-4 we have obj.setExcludeFromNav(boolean), but how about in plone 5?
It is giving me an error when my obj is a Folder.

AttributeError: setExcludeFromNav

the attribute doesn't exist apparently.

it is now called exclude_from_nav, so you can do obj.exclude_from_nav = True

Nope. dir(folder) doesn't have 'exclude_from_nav'

is folder an object, or a brain? you may need to get the object first

Is the Behavior enabled on the Folder? --> plone.app.dexterity.behaviors.exclfromnav.IExcludeFromNavigation

>>> import plone.app.dexterity.behaviors.exclfromnav as efn
>>> efn.IExcludeFromNavigationDefault(folder_obj) 
False

Is that it? If so, how do I change it to True? There is no setter.

Please check the type of Folder like @cdw9 says. If the Folder not a brain then you should enabled the Behavior via Configuration in the Plone Panel Dexterity->Folder->Behavior. If you enabled the behavior via Filesystem look in the Training Docs

This is so weird. I have the 'Exclude from Navigation' checkmarked in Dexterity. I also double checked to see if the line is in contenttypes. It is. So It should be enabled for all dexterity items.

I also checked the obj. It is a 'Folder' object but it doesn't have that property. Even 'Document' objects don't have the property either when they should. At first I thought maybe I am not getting the object, but there is no 'getObject()' on Document or Folder. :tired_face:

'getObject' is a Method of a Brain Object, not of Folder Object

True, so that means I actually have the Folder/Document obj. Yet there is no exclude_from_nav

was your folder created through the Plone UI ? migrated ? created by Api ?

Folders created by using portal.invokeFactory. Documents created by using api.content.create.

file_new_obj_dir = traverse_dir(absolute_url, portal)
file_new_obj = api.content.create(type='Document',container=file_new_obj_dir,title=title,safe_id=False,text = RichTextValue(text,'text/html','text/x-html-safe'))
transaction.commit()
file_new = file_new_obj_dir.get(file_new_obj.id)

Here file_new is the Document object just created. But it has no exclude_from_nav.

The get() isn't necessary, you already have the object. So you should be able to set file_new_obj.exclude_from_nav = True, then file_new_obj.reindexObject()

What version of Plone 5 are you using?

adapter = IExcludeFromNavigation(folder, None)
if adapter is not None:
    adapter.exclude_from_nav = True
    folder.reindexObject()

I understand what everyone is saying. However, there is no exclude_from_nav property. If I set it equal to True or False, it makes a property (I dislike this about python in general) and puts it in there, but then it never uses it. This tells me it is not the right property to set.

To make it more interesting, I randomly picked a folder and checked "exclude from navigation" in plone frontend, and it takes effect, but still the property of exclude_from_nav on the folder object is missing. Am I looking in the wrong place for it? Could it be somewhere else?

I am using:

Plone 5.0.8 (5018)
CMF 2.2.10
Zope 2.13.26
Python 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4]
PIL 3.3.0 (Pillow)

EDIT: I figured it out... turns out it was a case of a missing trailing slash :smiley:

Next time try to post a complete code snippet reproducing the problem, since this missing slash could not be caught by people trying to help you because there was nothing wrong in the part you posted.

1 Like

In case it helps, here is some code I use to retract and exclude from navigation the Users ('Members') folder on a site:

# retract and hide Users
if 'Members' in portal_ids:
    user_folder = portal['Members']
    wf_state = api.content.get_state(user_folder)
    if wf_state != 'private':
        api.content.transition(obj=user_folder, transition='retract')
    user_folder.exclude_from_nav = True
2 Likes

exclude_from_nav is a field in a dexterity schema and as a such it is not easily to be found by introspection.

For such fields I find helpful to look at the schemata and their fields of the object with something like the following (see below). This give me a hint of the adapter I need to access the field.

from plone.dexterity.utils import iterSchemata
from zope.schema import getFieldsInOrder

obj = # <- set your object here

for schema in iterSchemata(obj):
    for field in getFieldsInOrder(schema):
        print(u"    %s %s" % (field[0].ljust(18), schema))

The schemata and fields may vary depending on your object:

allow_discussion   plone.app.dexterity.behaviors.discussion.IAllowDiscussion
exclude_from_nav   plone.app.dexterity.behaviors.exclfromnav.IExcludeFromNavigation
id                 plone.app.dexterity.behaviors.id.IShortName
creators           plone.app.dexterity.behaviors.metadata.IOwnership
contributors       plone.app.dexterity.behaviors.metadata.IOwnership
rights             plone.app.dexterity.behaviors.metadata.IOwnership
effective          plone.app.dexterity.behaviors.metadata.IPublication
expires            plone.app.dexterity.behaviors.metadata.IPublication
subjects           plone.app.dexterity.behaviors.metadata.ICategorization
language           plone.app.dexterity.behaviors.metadata.ICategorization
title              plone.app.dexterity.behaviors.metadata.IBasic
description        plone.app.dexterity.behaviors.metadata.IBasic
text               plone.app.contenttypes.behaviors.richtext.IRichTextBehavior

In the case of exclude_from_nav the adapter is IExcludeFromNavigation which can be obtained with the following code (as pointed out by @1letter).

from plone.app.dexterity.behaviors.exclfromnav import IExcludeFromNavigation
adapter = IExcludeFromNavigation(obj, None)
if adapter is not None:
    obj.exclude_from_nav = True
    obj.reindexObject() # reindex the object after setting the field.

Other dexterity fields can be accessed in an analogous way.

1 Like