69

In a template, how do I get what page I'm currently on? I'd rather not pass a variable like page , especially when I know some request.xxx can provide me with the information.

<li {% if page=="home" %}class="active"{% endif %}>                   
    <a href="/">Home</a>                                                
</li>                                                                 
<li {% if page=="about" %}class="active"{% endif %}>                  
    <a href="/about">About</a>                                          
</li> 
Paco
  • 4,520
  • 3
  • 29
  • 53
atp
  • 30,132
  • 47
  • 125
  • 187

6 Answers6

73

As long as you've imported request, request.path should contain this information.

ranksrejoined
  • 1,229
  • 9
  • 9
  • 6
    Note that this is not true for other variables. It works because `request` is one of the variables [inserted by default](http://flask.readthedocs.org/en/latest/templating/#standard-context) into the template context. – Marcel M Mar 25 '13 at 14:39
64

Using request.path doesn't seem to be a proper approach since you'll have to update the paths in case of changing URL rules or deploying your site under a subfolder.

Use request.url_rule.endpoint instead, it contains actual endpoint name independent of actual path:

(Pdb) request.url_rule.endpoint
'myblueprint.client_pipeline'

In a template:

<li {% if request.url_rule.endpoint == "myblueprint.client_pipeline" %}class="active"{% endif %}>Home</li>

Good luck!

negus
  • 801
  • 6
  • 7
  • 7
    This is the correct answer. The others use hardcoded paths, which is a very bad idea. – Nathan Osman Dec 09 '14 at 19:53
  • 2
    This only works you are using one route per section of the page. Otherwise this won't be what you are looking for. =\ – flamusdiu May 28 '15 at 02:22
  • 1
    No, that's not true. You can have some structure in your endpoint names (like blueprint.subsection.page) and make the comparison using .startswith('blueprint.subsection.'). Just an example. – negus May 29 '15 at 03:25
50

First import request from flask in your application. Then you can use it without passing to template:

<li {%- if request.path == "/home" %} class="active"{% endif %}>
    <a href="/">Home</a>
</li>
<li {%- if request.path=="/about" %} class="active"{% endif %}>
    <a href="/about">About</a>
</li>
Community
  • 1
  • 1
Sosiska
  • 609
  • 4
  • 2
  • 2
    `request` imported (into `*.py` file), still getting error: jinja2.exceptions.UndefinedError: 'request' is undefined – Pavel Vlasov Feb 09 '18 at 21:15
11

To avoid using hard-coded URLs you can use the url_for function like this:

{% for ni in ['index', 'foo', 'bar', 'baz'] %}
<li {%- if request.path == url_for(ni) %} class="active"{% endif %}><a href="{{ url_for(ni) }}">{{ ni | capitalize }}</a></li>
{% endfor %}

In this case index, foo, bar and baz would be function names, used like this in your python code:

@app.route('/')
def index():
MoepMan
  • 111
  • 1
  • 4
5

Try

<li {% if request.endpoint == "blueprintname.routename" %}class="active"{% endif %}>Home</li>

This one worked for me.

bummi
  • 27,123
  • 14
  • 62
  • 101
iChux
  • 2,266
  • 22
  • 37
1

You can also use .split if your url has more stuff in it.

Example:

/product
/product/add
/product/32432/edit
/product/32432/view

{{ request.path.split('/')[1] }}

This will return only "product"

Iaron
  • 11
  • 1