Style active navigation element with a Flask/Jinja2 macro
Your code just defines a macro over and over again, it doesn't render anything. Avoid reading request.endpoint
and use base templates to do this.
base.html
<ul class="nav nav-pills">
<li class="{% block nav_here %}{% endblock %}">Here</li>
<li class="{% block nav_there %}{% endblock %}">There</li>
<li class="{% block nav_anywhere %}{% endblock %}">Anywhere</li>
</ul>
{% block content %}{% endblock %}
there.html
{% extends "base.html" %}
{% block nav_there %}active{% endblock %}
{% block content %}
<blockquote>No matter where you go, there you are.</blockquote>
{% endblock %}
The base navigation defines empty nav_
blocks in the li
class and the sub template sets the relevant one to active
. You can extend this as far as you want to have sub-navigation within pages too.
Changing the active class of a link with the twitter bootstrap css in python/flask
Have you looked at this ? https://jinja.palletsprojects.com/en/3.0.x/tricks/#highlighting-active-menu-items
Highlighting Active Menu Items
Often you want to have a navigation bar with an active navigation item. This is really simple to achieve. Because assignments outside of blocks in child templates are global and executed before the layout template is evaluated it’s possible to define the active menu item in the child template:
{% extends "layout.html" %}
{% set active_page = "index" %}
The layout template can then access active_page
. Additionally it makes sense to define a default for that variable:
{% set navigation_bar = [
('/', 'index', 'Index'),
('/downloads/', 'downloads', 'Downloads'),
('/about/', 'about', 'About')
] -%}
{% set active_page = active_page|default('index') -%}
...
<ul id="navigation">
{% for href, id, caption in navigation_bar %}
<li{% if id == active_page %} class="active"{% endif
%}><a href="{{ href|e }}">{{ caption|e }}</a>
</li>
{% endfor %}
</ul>
Add a nav bar to all templates
Create a base template with the layout and naviagation that will be common to all pages. Then extend this template to create the actual pages. Add blocks to the base template that can be overriden in the others.
base.html
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>{% block title %} - My Site {% endblock %}</title>
</head>
<body>
<div>Navbar</div>
{% block content %}{% endblock %}
</body>
</html>
index.html
{% extends 'base.html' %}
{% block content %}
<h3>{% block title %}Home{% endblock %}</h3>
<p>Hello, World!</p>
{% endblock %}
Note that the navbar is just defined in the base template. It does not need a block, and the content from the child templates will be substituded in after it.
You can use a similar technique to control which item is highlighted in a navigation bar.
Style active navigation element with a Flask/Jinja2 macro
Your code just defines a macro over and over again, it doesn't render anything. Avoid reading request.endpoint
and use base templates to do this.
base.html
<ul class="nav nav-pills">
<li class="{% block nav_here %}{% endblock %}">Here</li>
<li class="{% block nav_there %}{% endblock %}">There</li>
<li class="{% block nav_anywhere %}{% endblock %}">Anywhere</li>
</ul>
{% block content %}{% endblock %}
there.html
{% extends "base.html" %}
{% block nav_there %}active{% endblock %}
{% block content %}
<blockquote>No matter where you go, there you are.</blockquote>
{% endblock %}
The base navigation defines empty nav_
blocks in the li
class and the sub template sets the relevant one to active
. You can extend this as far as you want to have sub-navigation within pages too.
Dynamically setting active class with Flask and jinja2
The way the code appears in the editor is not causing any issues, but it could mean you don't a have a syntax/language support plugin/add-on installed.
If you're not getting any template errors (TemplateSyntaxError
, for example), it could be that the data in navigation_bar
or active_page
simply don't match. Could you include the data for these?
Alternatively, my go to is to have active_page
set on the base template and each page template:
{% set active_page = 'home' %}
and in navigation items I add:
<li class="other-styles {{'active' if active_page == 'the page' }}">
jinja2: Can I render template tags from an expression?
Other than {% include ... %}
and {% extends ... %}
, you're not going to be able to have the template system automatically render something that's added to a template during runtime without a bit of customization.
The beautiful part about Jinja 2 is that its API is very powerful and you can do many things without having to feel like your "hacking" the system. To do what your first example is implying, you just need to have the function render the included template snippet snd return a rendered string. If you're expecting the template to be rendered with the context of the parent template, that's not gonna happen automatically, but that's not a problem since you can pass in whatever you need directly in your function call in the template.
Flask raises TemplateNotFound error even though template file exists
You must create your template files in the correct location; in the templates
subdirectory next to the python module (== the module where you create your Flask app).
The error indicates that there is no home.html
file in the templates/
directory. Make sure you created that directory in the same directory as your python module, and that you did in fact put a home.html
file in that subdirectory. If your app is a package, the templates folder should be created inside the package.
myproject/
app.py
templates/
home.html
myproject/
mypackage/
__init__.py
templates/
home.html
Alternatively, if you named your templates folder something other than templates
and don't want to rename it to the default, you can tell Flask to use that other directory.
app = Flask(__name__, template_folder='template') # still relative to module
You can ask Flask to explain how it tried to find a given template, by setting the EXPLAIN_TEMPLATE_LOADING
option to True
. For every template loaded, you'll get a report logged to the Flask app.logger
, at level INFO
.
This is what it looks like when a search is successful; in this example the foo/bar.html
template extends the base.html
template, so there are two searches:
[2019-06-15 16:03:39,197] INFO in debughelpers: Locating template "foo/bar.html":
1: trying loader of application "flaskpackagename"
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- /.../project/flaskpackagename/templates
-> found ('/.../project/flaskpackagename/templates/foo/bar.html')
[2019-06-15 16:03:39,203] INFO in debughelpers: Locating template "base.html":
1: trying loader of application "flaskpackagename"
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- /.../project/flaskpackagename/templates
-> found ('/.../project/flaskpackagename/templates/base.html')
Blueprints can register their own template directories too, but this is not a requirement if you are using blueprints to make it easier to split a larger project across logical units. The main Flask app template directory is always searched first even when using additional paths per blueprint.
Related Topics
What's an Efficient Way to Find If a Point Lies in the Convex Hull of a Point Cloud
Efficient Calculation of Fibonacci Series
Pandas Get Column Average/Mean
Why Is Numpy's Einsum Faster Than Numpy's Built in Functions
Calling the "Source" Command from Subprocess.Popen
In Python, How to Import Filename Starts with a Number
How to Get Exit Code When Using Python Subprocess Communicate Method
Is the List of Python Reserved Words and Builtins Available in a Library
How to Generate All Possible Three Letter Strings
Pyqt Showing Video Stream from Opencv
Authentication Plugin 'Caching_Sha2_Password' Is Not Supported
Can Modules Have Properties the Same Way That Objects Can
What's the Difference Between "Pip Install" and "Python -M Pip Install"
Variable Assignment and Modification (In Python)
How to Convert a Currency String to a Floating Point Number in Python