django-simple-menu icon indicating copy to clipboard operation
django-simple-menu copied to clipboard

menus empty if generate_menu not called within same block.

Open nerdoc opened this issue 3 years ago • 3 comments

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?

nerdoc avatar Apr 12 '22 19:04 nerdoc

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...

nerdoc avatar Oct 27 '22 19:10 nerdoc

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.

nerdoc avatar Oct 27 '22 20:10 nerdoc

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

kytta avatar Oct 28 '22 18:10 kytta