news 2026/9/28 3:26:35

在 Flask 应用中集成 Folium 地图的三种实践方案:全屏渲染、iframe 嵌入与组件拆分

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Flask 应用中集成 Folium 地图的三种实践方案:全屏渲染、iframe 嵌入与组件拆分
  • 数据可视化
  • 数据分析
  • GIS

【免费下载链接】folium

Python Data. Leaflet.js Maps.

项目地址:https://gitcode.com/gh_mirrors/fo/folium
点击查看免费下载

导读

Folium 作为 Python 生态中基于 Leaflet.js 的地图可视化库,最常见的落地场景之一就是与 Flask 等 Web 框架集成,把交互式地图发布为网页服务。本文基于 docs/advanced_guide/flask.rst 官方指南及其配套示例 docs/_static/flask_example.py,系统讲解在 Flask 中嵌入 Folium 地图的三种方案:直接返回地图 HTML、以 iframe 嵌入现有页面、以及拆分地图组件(header / html / script)后手动组装。读完本文,你将能够独立搭建一个可运行的 Flask + Folium 应用,并理解每种方案背后的渲染原理与适用场景。

三种集成方案概览

官方文档明确指出:在 Flask 应用中使用 Folium 是一个常见需求,且存在多种实现方式。最简单的方式是直接返回地图的 HTML 表示;如果要把地图嵌入到已有的页面布局中,则可以选择嵌入 iframe,或者提取地图的各个组成部分(header、html、script)后手动插入页面。

这三种方式在 docs/_static/flask_example.py 中均有对应的可运行示例,分别对应三个路由:

路由方案核心调用
/全屏渲染m.get_root().render()
/iframeiframe 嵌入m.get_root()._repr_html_()
/components组件拆分header.render()/html.render()/script.render()

运行环境只需两个 Python 包:flask与folium。启动命令为:

$ python flask_example.py

启动后在浏览器访问http://127.0.0.1:5000/即可看到地图。

方案一:直接返回地图 HTML(全屏页面)

这是三种方式中最简单的一种,适用于地图本身占据整个页面的场景(如全屏可视化大屏、单一地图应用)。

from flask import Flask, render_template_string import folium app = Flask(__name__) @app.route("/") def fullscreen(): """Simple example of a fullscreen map.""" m = folium.Map() return m.get_root().render()

其核心在于m.get_root()。从 Folium 的渲染模型看,每个folium.Map对象在构造时都会被挂载到一个Figure(画布)对象上——在 folium/folium.py 的Map.__init__中有明确逻辑:

Figure().add_child(self)

因此get_root()返回的就是这个Figure实例,而Figure.render()会一次性产出完整的 HTML 文档(包含<head>、Leaflet 的 CSS/JS 链接、地图容器 div 以及初始化脚本)。Map类继承了JSCSSMixin(定义于 folium/elements.py),其中default_js与default_css列表(如 Leaflet 1.9.4、jQuery、Bootstrap 等资源的 CDN 链接)会在渲染时被注入到 figure 的 header 中,最终由 folium/folium.py 的JSCSSMixin.render()统一生成<script>与<link>标签。

由此可以理解该方案的特性:

  • 返回的是完整、独立的 HTML 文档,浏览器直接解析即可显示地图;
  • 不需要 Flask 模板引擎参与,代码最简;
  • 地图尺寸默认按folium.Map的width/height参数(默认"100%")呈现,适合整页场景。

从源码 folium/folium.py 的Map._template可以看到,页面布局相关的样式(位置、宽高、min-width/min-height、left/top)均由该模板中的header宏生成,这就是render()能输出完整页面布局的底层依据。

方案二:iframe 嵌入现有页面

当你的页面已经具备自己的导航栏、侧边栏或内容区布局,只想在地图区域嵌入一块交互地图时,iframe 是最省心的方式:地图与宿主页面互不干扰,样式完全隔离。

@app.route("/iframe") def iframe(): """Embed a map as an iframe on a page.""" m = folium.Map() # set the iframe width and height m.get_root().width = "800px" m.get_root().height = "600px" iframe = m.get_root()._repr_html_() return render_template_string( """ <!DOCTYPE html> <html> <head></head> <body> <h1>Using an iframe</h1> {{ iframe|safe }} </body> </html> """, iframe=iframe, )

这里有几个关键点值得展开:

1. 尺寸控制。示例通过直接修改 figure 的属性来设定地图区域大小:

m.get_root().width = "800px" m.get_root().height = "600px"

在 folium/folium.py 中,width与height参数在Map.__init__里会经过_parse_size解析成(数值, 单位)的二元组,并分别记录_width_is_percent/_height_is_percent标志;模板中据此区分使用vw/vh(百分比)还是固定像素值(同时设置min-width/min-height)。因此你也可以传入"100%"、"50%"等百分比字符串,或者直接使用folium.Map(width=800, height=600)的构造参数形式。

2._repr_html_()的作用。Map._repr_html_方法定义于 folium/folium.py:

def _repr_html_(self, **kwargs) -> str: """Displays the HTML Map in a Jupyter notebook.""" if self._parent is None: self.add_to(Figure()) self._parent: Figure out = self._parent._repr_html_(**kwargs) self._parent = None else: out = self._parent._repr_html_(**kwargs) return out

它在 Jupyter 中用于地图的富文本显示,而在 Flask 场景下被"借用"来生成一段内联的 HTML 片段。这里需要特别注意:示例中调用的是m.get_root()._repr_html_()(即 figure 的_repr_html_),它返回的是包含完整<style>、<script>与地图容器 div 的自包含片段,因此可以直接塞进{{ iframe|safe }}渲染。

3. Jinja2 的安全转义。由于地图 HTML 片段包含大量<script>与<style>标签,而 Jinja2 默认会转义 HTML,模板中必须使用|safe过滤器(如{{ iframe|safe }})告知 Jinja2 这是可信的原始 HTML,否则地图将无法正常显示。

iframe 方案的优点:宿主页面结构清晰、地图样式不会污染页面其他元素;缺点:地图内外的交互隔离(如无法跨 iframe 调用地图 API),且每次请求都会额外渲染一份完整的自包含文档。

方案三:拆分地图组件(header / html / script)

这是最灵活、也是最能体现 Folium 渲染架构的方案:把地图拆解成三段独立的 HTML 片段,分别插入到宿主页面的<head>与<body>中。

@app.route("/components") def components(): """Extract map components and put those on a page.""" m = folium.Map( width=800, height=600, ) m.get_root().render() header = m.get_root().header.render() body_html = m.get_root().html.render() script = m.get_root().script.render() return render_template_string( """ <!DOCTYPE html> <html> <head> {{ header|safe }} </head> <body> <h1>Using components</h1> {{ body_html|safe }} <script> {{ script|safe }} </script> </body> </html> """, header=header, body_html=body_html, script=script, )

执行顺序的意义。示例先调用m.get_root().render()再分别渲染各段,这并非冗余:Figure.render()会先遍历并渲染整棵元素树,把 Leaflet 初始化脚本、CSS/JS 资源链接、地图容器等依次写入 figure 内部的header、html、script三个子容器。从 Folium 的类继承关系可以推断(参见 folium/elements.py 与 folium/folium.py 的JSCSSMixin.render()):figure 的header会承载 Leaflet 等外部资源的<link>与<script>引用,html存放地图容器<div class="folium-map">,script存放L.map(...)等初始化 JavaScript。三段之间是严格的前置依赖——CSS 必须在 body 渲染前加载、JS 初始化脚本必须放在地图容器之后,因此示例把header放进<head>、body_html放进<body>顶部、script包进<script>标签放在最后,这一顺序是保证地图正常显示的关键。

与方案二的区别。方案二生成的 iframe 片段是"打包好"的自包含 HTML;而方案三把 CSS、DOM、JS 拆开,让你可以:

  • 复用宿主页已有的头部资源(header 可按需取舍);
  • 在script前后追加自定义 JavaScript;
  • 将body_html精确放置在页面任意布局位置;
  • 摆脱 iframe 的隔离限制,实现页面与地图的脚本级互通。

该方案代价是需要手工保证三段顺序与闭合标签正确,出错概率略高,建议封装为可复用的模板片段。

实战:搭建完整运行环境

  1. 安装依赖:pip install flask folium。注意 Folium 的运行时依赖(见 requirements.txt):branca>=0.6.0(提供Figure、Element等底层元素体系)、jinja2>=2.9(模板渲染引擎)、numpy、requests与xyzservices。在 folium/init.py 中还有版本硬校验:若branca低于 0.3.0 会直接抛出ImportError。
  2. 保存示例:将 docs/_static/flask_example.py 完整保存为flask_example.py(或复制到examples/目录运行)。
  3. 启动服务:
$ python flask_example.py

示例末尾的app.run(debug=True)会以调试模式启动开发服务器,默认监听127.0.0.1:5000。浏览器分别访问:

  • http://127.0.0.1:5000/—— 全屏地图;
  • http://127.0.0.1:5000/iframe—— iframe 嵌入页;
  • http://127.0.0.1:5000/components—— 组件拆分页。

debug=True仅在开发阶段使用,生产部署(如 gunicorn、uWSGI 或平台化托管)时务必关闭调试模式,并考虑将地图渲染结果缓存,因为render()每次都会重新执行完整的模板渲染流程。

常见问题与调优建议

  • 地图不显示:优先检查是否为{{ iframe|safe }}之类的 Jinja2 变量漏加了|safe过滤器;若手写模板,再确认 header 位于<head>、script 位于地图 div 之后。
  • 地图尺寸不对:通过folium.Map(width=..., height=...)构造参数或m.get_root().width / height调整,支持像素整数与百分比字符串两种写法;模板中百分比会被渲染为vw/vh(见 folium/folium.py 的Map._template)。
  • 需要多地图共存:每个folium.Map实例都会被赋予唯一的get_name()(如map_xxxxx),即使在同一页面渲染多张地图,变量名也不会冲突,这一点从Map._template中var {{ this.get_name() }} = L.map(...)的变量命名方式可以得到验证。
  • 生产环境资源加载:Folium 默认通过 CDN 加载 Leaflet 1.9.4、jQuery 等资源(见 folium/folium.py 的_default_js/_default_css),内网或离线环境需改用add_js_link/add_css_link(定义于 folium/elements.py)替换为自建静态资源地址。

总结

Folium 与 Flask 的集成虽然入门简单,但理解其渲染模型会让你的集成方案更有章法:get_root()拿到底层Figure,render()输出完整页面,_repr_html_()生成自包含片段,header/html/script三个子容器则对应 CSS 资源、DOM 容器与初始化脚本。三种方案从"整页"到"片段"再到"组件级控制",覆盖了从最小演示到复杂布局整合的全部常见场景,官方示例 docs/_static/flask_example.py 可直接作为项目脚手架使用。

  • 数据可视化
  • 数据分析
  • GIS

【免费下载链接】folium

Python Data. Leaflet.js Maps.

项目地址:https://gitcode.com/gh_mirrors/fo/folium
点击查看免费下载
上一篇:ComfyUI ControlNet Aux插件:模型下载失败问题的终极解决方案
下一篇:CC Switch 切换 Codex 供应商后旧会话续聊失败?三步切回加一条命令快速定位指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 3:26:33

解决网站被黑挂马:wordpresshtml5插件下载与对比评测实战指南

解决网站被黑挂马:wordpresshtml5插件下载与对比评测实战指南 网站被黑挂马不知道怎么办?很多站长在收到Google Search Console的安全警告后,第一反应是慌乱重启服务器,结果第二天病毒又回来了。这种反复感染的情况,往往是因为你依赖的第三方插件存在漏洞,而你在下载wordpr…

作者头像 李华
网站建设 2026/9/28 3:26:30

揭秘seo服务如何收费:性能优化背后的真实成本

揭秘seo服务如何收费:性能优化背后的真实成本 域名服务器搞不懂,很多老板一上来就问“这个怎么搞”。别急,先看看你现在的网站,打开浏览器F12,看Network面板。如果加载一张图要5秒,首屏白屏时间超过3秒,别谈什么SEO,先把性能优化做了。…

作者头像 李华
网站建设 2026/9/28 3:26:26

网站建设简单合同模板下载图解步骤避坑指南

网站建设简单合同模板下载图解步骤避坑指南 网站被黑挂马、首页变黄图、后台密码失效,这种噩梦场景谁没经历过?很多站长在事后才想起当初签约时那些模糊不清的条款,这时候手里有一份清晰的 网站建设简单合同模板 就成了救命稻草。别等到出了大事才后悔没把权责写明白,今天这篇 图解步骤…

作者头像 李华
网站建设 2026/9/28 3:26:02

三极管与MOS管快速关断电路设计:从原理到实战调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 3:25:56

信息技术九年级上册网站咋做从零搭建

九年级网站咋做?3个实战案例教你搞定域名与服务器 域名解析报错,服务器端口不通,这种“域名服务器搞不懂”的坑,我见过太多新手栽进去。很多学生或刚入行的开发者,拿到“信息技术九年级上册网站咋做”这个题目,第一反应不是写代码,而是对着路由器发呆。别急,今天不讲虚的,直接上 实战案例…

作者头像 李华