Description
Summary
Sometimes when you are not logged in breadcrumb will not show all nodes if selected node is from CMSAttachMenu for an AppHook.
Let's use the following URL structure:
/ (CMS Page)
|-- /my-app/ (CMS Page with attached AppHook with menus)
|-- /my-app/slug/ (URL handled from AppHook. There is `NavigationNode` for it by custom `CMSAttachMenu`)
We are opening /my-app/slug/
Expected behaviour
We expect the breadcrumb to show:
/
-> /my-app/
-> /my-app/slug/
Actual behavior
When you are logged out it randomly only shows:
/
-> /my-app/
Environment
- Python version: < 3.6
- Django version: 1.11.*
- django CMS version: 3.5.2
The issue does not occur on Python 3.6
Extra details
I'm not sure if #6514 is related or not.
From my observations the cause for my problem is that in the {% show_breadcrumb %}
the currently selected node is got by the following code:
selected = next((node for node in nodes if node.selected), None)
which will find the first node with is marked as selected.
The problem is that in the nodes
list if there are extensions there can be more than one selected node (at least from what I found). In my case both /my-app/
and /my-app/slug/
was marked as selected. Depending on the order of the nodes
if the right one was found first then the breadcrumb will be shown correctly, if the wrong one was first then there will be missing elements in the breadcrumb.
This problem does not occur in Python 3.6 (CPython 3.6) because dict
s are ordered (preserve insertion order). My custom menu is registered in the menu pool as soon as server starts. On the other hand CMSMenu
is registered on first request. For that reason when building the list of nodes in Python 3.6 custom nodes always comes before nodes for CMS pages and everything works fine. In Python >= 3.3 < 3.6 dicts has random order on every interpreter start which makes this problem inconsistent (sometime works, sometimes not).
I was not tested with Python 2.7 (there order of dicts should be somewhat predictable)
The problem also does not occur when in edit mode because for some reason the node for the page is not marked as selected.
There are few possible solutions that came to my mind:
- No matter how many selected nodes there are in the list (I think maximum of two - the node for the CMS page with AppHook and the node for the actual view) to use the node with higher level.
- Ensure that there is only one selected node in the list.
- Use
OrderedDict
for Python versions < 3.6 inMenuPool.menus
and local variableregistered_menus
inMenuPool.get_registered_menus
which is returned as result and then assigned toMenuRenderer.menus