Reputation: 1373
I want to insert follium map into the jinja template.
run.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
start_coords = (46.9540700, 142.7360300)
folium_map = folium.Map(location=start_coords, zoom_start=14)
folium_map.save()
return render_template('index.html', folium_map=folium_map)
if __name__ == '__main__':
app.run(debug=True)
template/index.html - jinja template for Flask
{% extends "layout.html" %}
{% block title %}Test{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}
{% block body %}
**<div><!--Folium map here-->{{ folium_map }}</div>**
{% endblock %}
My site shows current line:
<folium.folium.Map object at 0x00000000069D5DA0>
But I need map that generate method follium_map.save('map.html') in this div block.
How can I do this?
Upvotes: 17
Views: 18860
Reputation: 647
Maybe it can be the solution. First we save a Folium map as an html file on templates folder. Then we create a Flask route to render another html file. On that html file, we create an iframe element that call our map.
Here is the file structure:
proectApp
├── app.py
└── templates
├── index.html
└── map.html
Folium map file (map.html) will be created automatically from my app.py. On app.py I'll create 2 main route: the first one is the home route which will render index.html & create map.html. Then the other is to render folium map (map.html). Here are the codes:
app.py
from flask import Flask, render_template
import folium
app = Flask(__name__)
@app.route('/')
def index():
start_coords = (-6.1753924, 106.8271528)
folium_map = folium.Map(
location=start_coords,
zoom_start=17
)
folium_map.save('templates/map.html')
return render_template('index.html')
@app.route('/map')
def map():
return render_template('map.html')
if __name__ == '__main__':
app.run(debug=True)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Folium Map</title>
</head>
<body>
<h1>Render Folium on Flask 🌏</h1>
<iframe class="map", src="/map" width="600" height="600"></iframe>
<h3><b style="background-color: lightcoral; color: lightcyan;">
Render Folium on Flask done!
</b></h3>
</body>
</html>
The result will be shown on browser like this:
Hope it helps you.
Upvotes: 7
Reputation: 73
Indeed, the best way to do that is following the documentation of Folium:
Insert in your Flask file this:
@app.route('/**map**')
def flask_map():
return **your_folium_map**._repr_html_()
Insert in you HTML file this: <iframe class="**map**", src="/map" width="900" height="600"></iframe>
DONE!
you don't need to convert your folium map in a html and you shouldn't use it as source to render it in your html page. use the 1) instead if you don't want to have future problems in rendering it.
Upvotes: 0
Reputation: 772
This may help in your jinja template:
{{ folium_map | safe }}
Upvotes: 0
Reputation: 31236
A different solution using iframe and render_template
<iframe class="map", src="/get_map" width="1100" height="600"></iframe>
Plus python flask code
# a hack going on here as web servers are caching folium generated template
# randomly move to a new name and then use render_template
@app.route('/get_map')
def get_map():
r = int(random.triangular(0,100))
t = "templates/map_{i}.html"
for i in range(0,100):
f = t.format(i=i)
if os.path.exists(f):
os.remove(f)
f = t.format(i=r)
shutil.copy("templates/map.html", f)
r = make_response(render_template(os.path.split(f)[1]))
r.cache_control.max_age = 0
r.cache_control.no_cache = True
r.cache_control.no_store = True
r.cache_control.must_revalidate = True
r.cache_control.proxy_revalidate = True
return r
Without the copy to a random filename before rendering httpd (on AWS beanstalk) / flask debug environment was not picking up new instance of folium html template. cache_control is not needed but was part of what I trialed to come to a solution. Clearly this solution is not thread safe
Upvotes: 1
Reputation: 3493
You could save your generated html with folium_map.save('templates/map.html')
. Then you can use jinja2 to {% include "map.html" %}
. The generated html does not render a map when wrapped in div tags as indicated, if encapsulation is necessary consider using iframes or custom folium templates.
file structure
myapp
├── run.py
└── templates
├── index.html
└── layout.html
run.py
from flask import Flask, render_template
import folium
app = Flask(__name__)
@app.route('/')
def index():
start_coords = (46.9540700, 142.7360300)
folium_map = folium.Map(location=start_coords, zoom_start=14)
folium_map.save('templates/map.html')
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
layout.html
<!DOCTYPE HTML>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<header>{% block head %}{% endblock %}</header>
{% block body %}{% endblock %}
</body>
</html>
index.html
{% extends "layout.html" %}
{% block title %} Test {% endblock %}
{% block head %} {{ super() }} {% endblock %}
{% block body %}
{% include "map.html" %}
{% endblock %}
Upvotes: 12