想法 / One simple idea
最近在折腾研究Python Web开发,入坑了Flask,用习惯Python了发现用它干啥都是~真香!
试着写了个考试管理的后台,以前做web开发的套路,管理后台用传统的iFrame来加载和切换不同功能页面,感觉很low,完全无法愉快的装X啊~之前看过一篇用Flask+VUE做单页面应用的教程(传送门),也感受过了VUE的魅力,各种双向绑定6的飞起,不过像我这种泥腿子开发而言,还是有点复杂了,套路太深,还是想想怎么用好Python原生的Flask轮子来搞吧.研究了半天Jinja模板的用法,配上ajax异步获取局部页面的HTML数据,搞起来也是挺方便的.
好了,想法啰嗦完毕,开始进入正题!
实现效果
文件结构
.
├── app.py # Flask主程序入口
├── static # 静态调用文件
│ ├── css
│ ├── img
│ ├── js
│ └── vendor
└── templates # 模板
├── admin # 后台模板
│ ├── admin.html
│ ├── admin_base.html
│ ├── dashboard.html
│ └── detail.html
├── base.html # 下面这些是首页相关模板,请忽视
├── index.html
├── index2.html
└── login.html
补充一下,后台使用了SBAdmin2模板,传送门在此
吐槽一下,这货是Start Bootstrap的缩写,真是够SB的了,哈哈~
Flask后台代码
添加路由/admin
获取GET方式传入的type变量,根据变量内容输出不同内容渲染的HTML代码
render_template
函数返回的值其实就是HTML文本数据,可以直接用在后面使用ajax异步调用
"""Flask主程序
Returns:
[type] -- [description]
"""
from flask import Flask, request, render_template
from flask_cors import CORS
DEBUG = False
TEMPLATES_AUTO_RELOAD = True
JSON_AS_ASCII = False
app = Flask(__name__)
app.config.from_object(__name__)
CORS(app)
@app.route('/admin', methods=['GET'])
def admin():
"""后台管理获取局部渲染HTML数据
"""
data = request.values
if data['type'] == 'dashboard':
return render_template('/admin/dashboard.html')
if data['type'] == 'detail':
return render_template('/admin/detail.html')
if __name__ == '__main__':
app.run(host='0.0.0.0')
模板
admin_base.html
就是正常的HTML,这里主要是需要用到Flask内置的jinja2模板语法中的模板块{% block body %}{% endblock %}
其中的body和script是自己起的块名称,可以自行修改,该模板作为基础模板,其中设置的两个块会在后面的其他模板继承的时候进行填充.
【划重点】
引用静态的css和js文件需要使用/static/
内置的路径变量
<!DOCTYPE html>
<html lang="en" class="h-100">
<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>文明单位测试平台-管理后台</title>
<link href="/static/css/sb-admin-2.min.css" rel="stylesheet">
<link href="/static/css/lian.css" rel="stylesheet">
</head>
<body id="page-top" data-gr-c-s-loaded='true'>
{% block body %}{% endblock %}
</body>
<script src="/static/vendor/jquery/jquery.min.js"></script>
<script src="/static/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="/static/vendor/jquery-easing/jquery.easing.min.js"></script>
<script src="/static/js/sb-admin-2.min.js"></script>
<script src="/static/js/echarts.min.js"></script>
{% block script %}{% endblock %}
</html>
admin.html
注意开头的{% extends "/admin/admin_base.html" %}
声明了该模板是从admin_base.html继承而来,下面分别对基础模板中挖的两个坑body和script块进行了内容的填充.
自定义的getContent(type)
函数用于点击菜单栏中项目进行异步加载页面主体区域内容,这里需要注意$.ajax
函数中的dataType
参数需要设置为html
{% extends "/admin/admin_base.html" %}
{% block body %}
<div id="wrapper">
<!-- 左侧菜单栏 -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- 左侧菜单栏 - 标题 -->
<a class="sidebar-brand d-flex align-items-center justify-content-center">
<div class="sidebar-brand-text mx-3">考试管理后台</div>
</a>
<!-- 分割线 -->
<hr class="sidebar-divider my-0">
<!-- 导航菜单项目 - 状态总览 -->
<li class="nav-item active">
<a class="nav-link" href="#" onclick="getContent('dashboard')">
<span>状态总览</span></a>
</li>
<!-- 分割线 -->
<hr class="sidebar-divider">
<!-- 分组标题 -->
<div class="sidebar-heading">
成绩查看
</div>
<!-- 导航菜单项目 - 单人成绩 -->
<li class="nav-item">
<a class="nav-link" href="#" onclick="getContent('detail')">
<span>单人成绩</span></a>
</li>
</ul>
<!-- 左侧菜单栏结束 -->
<!-- 右侧主体层 -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- 主体层 -->
<div id="content">
<!-- 顶部工具栏 -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<ul class="navbar-nav">
<p>这里是顶部工具栏</p>
</ul>
</nav>
<!-- 顶部工具栏结束 -->
<!-- 主体内容区域 -->
<div class="container-fluid" id="main">
<div class="jumbotron">
<h1>这里是默认显示的主体内容区域</h1>
</div>
</div>
<!-- 主体内容区域结束 -->
</div>
<!-- 主体层结束 -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright © 这里是Footer底部版权栏</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- 右侧主体层结束 -->
</div>
{% endblock %}
{% block script %}
<script>
// 通过type变量选择要获取的渲染内容
function getContent(type) {
$.ajax({
type: 'GET',
url: '/admin',
data: { 'type': type },
dataType: 'html',
success: function (data) {
$("#main").html(data);
}
});
}
</script>
{% endblock %}
dashboard.html & detail.html
这里就不上代码了,就是用在使用ajax异步从/admin
地址处获取到的HTML内容