menus empty if generate_menu not called within same block.
the docs say that {% generate_menu %} needs to be called within a block. I think this is not correct, as it seems to need to be called within the same block you are using the menu.
Using a simple pattern to demonstrate this:
# base.html template
<html>
<head>
</head>
<body>
{% block generate_menu %}
{% generate_menu %}
{% endblock %}
{% block content %}
Empty page.
{% endblock %}
</body>
</html>
Now use a template that inherits this:
# application.html
{% extends 'base.html' %}
{% block content %}
Now you should see menus, but you don't.
{{ menus }}
{% endblock %}
Here you just override the content block. The generate_menu block should be inherited by extend and be untouched, so generate_menu should be called - which I can confirm by debugging.
The problem seems to be that the context which is passed to MenuNode.render() does't seem to get passed through to the correct template in application.html.
If I add {% generate_menu %} within the content block in application.html, everything is ok. Even if I add {% generate_menu %} in a new generate_menu block in application.html (which is "a block", like the docs say), it does NOT work.
Is this intended behaviour? Or a bug?
I know a bit more now. See in an example here with a base.html:
{% load menu %}
<html>
<head></head>
<body>
{% block menu_wrapper %}
{% generate_menu %}
{% endblock %}
{% block body %}{% endblock %}
</body>
</html>
...and here a template that extends it:
{% extends 'base.html' %}
{% load menu %}
{% block body %}
{{ menus }} <!-- do something with the menus here -->
{% endblock %}
This does not work, as stated earlier. BUT, if you put the block containing the generate_menu as wrapper around a block that is extended in a sub template, it works:
{% load menu %}
<html>
<head></head>
<body>
{% block menu_wrapper %}
{% generate_menu %}
{% block body %}{% endblock %}
{% endblock %}
</body>
</html>
You might ask, why the heck do you need a separate block for generate_menu? Because I had used django_hosts in a complicated, dynamic setup, and wanted to let the sub template decide if it needs menus at all. If not, it would eventually override the menu_wrapper with empty content, so suppressing menu generation.
I ditched django_hosts later, but the separate block remained in my base html - so the bug stayed with me.
I think I could live with seeing this as not a bug, but a "certain behaviour". But it should be stated in the docs as the sentence there is a bit misleading:
Note that generate_menu must be called inside of a block.
I would change that. it's even not good practice, as suggested there, to run generate_menu within a sub template. It is sufficient to run once, in the base (most root) template: BUT, it must be within a block, that's true. So the only way I can think of is like in my second example above: to put a menu_wrapper block around everything else. - And just don't override this block...
AAARGH. Sorry for the spam. It's much easier...
{% load menu %}
<html>
<head></head>
<body>
{% generate_menu %}
{% block body %}{% endblock %}
</body>
</html>
I was blinded by the docs because they say it has to be within a block. It hasn't in fact. Or only, if using in a sub template that extends another.
So: best practice is: put it into the main, root template, just anywhere. No block needed. Exactly said, DON'T put it in a block in your root template, as this will most certainly be overridden.
I was blinded by the docs because they say it has to be within a block. It hasn't in fact. Or only, if using in a sub template that extends another.
Incredible! I didn't know this, either! Thank you a lot!
So: best practice is: put it into the main, root template, just anywhere. No block needed. Exactly said, DON'T put it in a block in your root template, as this will most certainly be overridden.
I will make sure to update the docs