文章目录
- Flask案例
- 开源地址
- 简介
- 一、环境搭建
- 1.1 canda常用命令
- 1.2 创建虚拟环境
- 1.3 安装flask
- 1.4 导入flaskdemo项目
- 二、项目配置
- 2.1 开启DEBUG
- 2.2 配置数据库连接参数
- 2.3 安装项目依赖
- 2.4 修改flaskdemo中的错误
- 三、组件
- 3.1 flash
- 3.2 pagination
- 3.3 table
- 3.4 nav
- 3.5 form
- 3.6 搜索框
- 四、Ajax
- 4.1 定义
- 4.2 jQuery Ajax语法
- 4.3 jQuery Ajax函数参数
- 4.4 基本Ajax请求方法
- 五、echarts
- 5.1 简单demo
- 5.2 Echarts结合flask
- 5.3 Echarts结合Ajax
Flask案例
开源地址
https://github.com/854771076/flaskdemo
简介
Flask是一个非常小的PythonWeb框架,被称为微型框架;只提供了一个稳健的核心,其他功能全部是通过扩展实现的;意思就是我们可以根据项目的需要量身定制,也意味着我们需要学习各种扩展库的使用。
一、环境搭建
1.1 canda常用命令
获取版本号 | conda -V |
---|---|
conda --version | |
获取帮助 | conda -h |
conda --help | |
获取环境相关命令的帮助 | conda env -h |
所有 --单词 都可以用 -单词首字母来代替 | 比如 -version 可以用 -V来代替,只不过有的是大写,有的可能是小写 |
创建环境 | conda create -n environment_name |
---|---|
创建指定python版本下包含某些包的环境 | conda create -n environment_name python=3.7 numpy scipy |
进入环境 | conda activate environment_name |
退出环境 | conda deactivate |
删除环境 | conda remove -n yourname --all |
列出环境 | conda env list / conda info -e |
复制环境 | conda create --name new_env_name --clone old_env_name |
指定目录下生成环境yml文件 | conda env export > 目录/environment.yml |
从yml文件创建环境 | conda env create -n env_name -f environment.yml |
安装包 | conda instal package_name |
---|---|
查看当前环境包列表 | conda list |
查看指定环境包列表 | conda list -n environment_name |
查看conda源中包的信息 | conda search package_name |
更新包 | conda update package_name |
删除包 | conda remove package_name |
清理无用的安装包 | conda clean -p |
清理tar包 | conda clean -t |
清理所有安装包及cache | conda clean -y --all |
更新anaconda | conda update annaconda |
1.2 创建虚拟环境
conda create -n flaskdemo python=3.8
1.3 安装flask
#进入flask虚拟环境
conda activate flaskdemo
#虚拟环境安装flask
pip install flask
1.4 导入flaskdemo项目
-
打开flaskdemo项目
-
配置项目启动项
-
选择app文件和环境
二、项目配置
2.1 开启DEBUG
#config.py
DEBUG='on'
2.2 配置数据库连接参数
#config.py
user = 'root'
#数据库用户名
password = '123456'
#数据库密码
database = ''
#数据库名
host = '127.0.0.1'
#数据库ip
port = '3306'
#数据库端口
2.3 安装项目依赖
#安装python第三方库
pip install flask_sqlalchemy
pip install bootstrap_flask
pip install flask_wtf
2.4 修改flaskdemo中的错误
#app_bootstrap.py#index函数
pagination = Astock.query.paginate(page=page, per_page=20)
#test_pagination函数
pagination = Astock.query.paginate(page=page, per_page=10)#修改完成后即可运行项目,项目里面是bootstrap-flask的各种组件模板
三、组件
这里基于flaskdemo里面的组件模板进行解释,了解更多请看[bootstrap-flask官方文档](Bootstrap-Flask — Bootstrap-Flask 2.2.x 文档)
了解更多bootstrap知识,请看Bootstrap中文网 (bootcss.com)
3.1 flash
- flash组件用于消息的提醒,该demo中列举了许多例子如下图
- 在视图函数中可定义flash组件的样式
#app_bootstrap.py
#flash组件模板视图
@app.route('/flash', methods=['GET', 'POST'])
def test_flash():#flash函数第一个参数是消息内容,第二个参数则是消息的类型(默认类型为primary)#消息的类型主要有primary、secondary、success、danger、warning、info、light、darkflash('A simple default alert—check it out!')flash('A simple primary alert—check it out!', 'primary')flash('A simple secondary alert—check it out!', 'secondary')flash('A simple success alert—check it out!', 'success')flash('A simple danger alert—check it out!', 'danger')flash('A simple warning alert—check it out!', 'warning')flash('A simple info alert—check it out!', 'info')flash('A simple light alert—check it out!', 'light')flash('A simple dark alert—check it out!', 'dark')#Markup函数使消息内部的HTML标签能够转义flash(Markup('A simple success alert with <a href="#" class="alert-link">an example link</a>. Give it a click if you like.'),'success')return render_template('bootstrap_flash.html')
- 模板文件加载flash
#xxx.html
{% from 'bootstrap4/utils.html' import render_messages %}
#dismissible是是否开启关闭按钮的选项
{{ render_messages(container=False, dismissible=True) }}
- 可关闭的flash组件
#base.html
#因为base.html中只载入了bootstrap的css文件,需要在head中载入bootstrap的js文件后,点击消息的x按钮就可以关闭消息框
#导入js
{{ bootstrap.load_js() }}
#开启可关闭选项
{{ render_messages(container=False, dismissible=True) }}
3.2 pagination
- 该demo列举了两种分页器样式
- 分页功能视图函数
#app_bootstrap.py@app.route('/pagination', methods=['GET', 'POST'])
def test_pagination():#定义一个变量page来获取前端翻页按钮传来的GET请求参数pagepage = request.args.get('page', 1, type=int)#对数据库对象Astock进行分页,page是页数,per_page是每一页的条数pagination = Astock.query.paginate(page=page, per_page=10)#获取分页后当前页的数据messages = pagination.items#将分页器对象和分页数据返回到模板return render_template('bootstrap_pagination.html', pagination=pagination, messages=messages)
- 分页器模板
#xxx.html
#导入组件
{% from 'bootstrap4/pagination.html' import render_pager, render_pagination %}
#分页器样式一(只有上一页,下一页)
{{ render_pager(pagination) }}
#分页器样式二
{{ render_pagination(pagination) }}
3.3 table
- 视图函数
#app_bootstrap.py@app.route('/table')
def test_table():#同分页器page = request.args.get('page', 1, type=int)pagination = Astock.query.paginate(page=page, per_page=20)messages = pagination.items#表格需要显示的字段名,格式为(数据库字段名,表格显示字段名)titles = [('id', '#'), ('stockid', '股票代码'), ('stockname', '股票名称'), ('company', '公司名称'), ('createtime', '上市时间'),('category', '行业分类'), ('desc', '主营业务')]#将数据、表头、数据库对象返回至前端模板return render_template('bootstrap_table.html', messages=messages, titles=titles, Astock=Astock)
- 表格模板
#xxx.html
#导入组件
{% from 'bootstrap4/table.html' import render_table %}
#判断是否有数据传入
{% if messages %}
#messages是后端查询到的表格数据,titles是表头,table_classes是表格的样式,show_actions是是否显示操作列,model是数据库模型,view_url是详细页按钮,参数格式为(视图函数名, [(请求参数名, :数据库字段名)])
{{ render_table(messages, titles, table_classes='table-responsive table-striped',header_classes='thead-dark',show_actions=True, model=Astock,view_url=('view_message', [('message_id', ':stockid')]))}}
{% endif %}
3.4 nav
-
该demo有两种nav
-
视图函数
#app_bootstrap.py@app.route('/nav', methods=['GET', 'POST'])
def test_nav():return render_template('bootstrap_nav.html')
- 导航模板
#xxx.html
#导入组件
{% from 'bootstrap4/nav.html' import render_nav_item, render_breadcrumb_item %}#bootstrap官网copy的样式
<nav class="navbar navbar-expand-lg navbar-light bg-light"><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarSupportedContent"><div class="navbar-nav mr-auto">#导航栏子项,render_nav_item(视图函数, 显示名称){{ render_nav_item('test_form', 'Form') }}{{ render_nav_item('test_nav', 'Nav') }}{{ render_nav_item('test_pagination', 'Pagination') }}{{ render_nav_item('test_flash', 'Flash Messages') }}</div></div></nav>
3.5 form
- 表单类定义
#form.py
#导包
from flask_bootstrap import SwitchField
from wtforms import Form, StringField,BooleanField,SubmitField, ValidationError,PasswordField
from flask_wtf import FlaskForm
from wtforms.fields import *
from wtforms.validators import DataRequired, Length, Regexp
#表单类需要继承FlaskForm
class ExampleForm(FlaskForm):#定义表单字段#description 添加字段描述#render_kw 可添加HTML属性(如class、id、placeholder等)date = DateField(description="We'll never share your email with anyone else.") datetime = DateTimeField(render_kw={'placeholder': 'this is a placeholder'}) datetime_local = DateTimeLocalField()time = TimeField()floating = FloatField()integer = IntegerField()decimal_slider = DecimalRangeField()integer_slider = IntegerRangeField(render_kw={'min': '0', 'max': '4'})email = EmailField()url = URLField()search = SearchField()telephone = TelField()#validators 设置验证属性image = FileField(render_kw={'class': 'my-class'}, validators=[Regexp('.+\.jpg$')]) #choices 添加表单元素的可选项option = RadioField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')])select = SelectField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')])select_multiple = SelectMultipleField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')])bio = TextAreaField()title = StringField()secret = PasswordField()remember = BooleanField('Remember me')submit = SubmitField()
- 表单模板
#xxx.html
{% from 'bootstrap4/form.html' import render_form, render_field, render_form_row %}
#render_form 直接打印整个表单,有三个常用参数(表单模型,处理url,请求方法)
{{ render_form(form,'/form','get') }}
#表示用get请求的方式将表单传递给/form路由对于的视图函数处理
#render_field打印单个表单元素
{{ render_field(form.username) }}
#render_form_row打印一行表单元素
{{ render_form_row([form.username, form.password]) }}
- 表单视图
#app_bootstrap.py@app.route('/form', methods=['GET', 'POST'])
def test_form():form = HelloForm()#验证表单if form.validate_on_submit():flash('Form validated!')#通过验证则返回index路由return redirect(url_for('index'))return render_template('bootstrap_form.html',#返回表单对象到模板form=form,telephone_form=TelephoneForm(),contact_form=ContactForm(),im_form=IMForm(),button_form=ButtonForm(),example_form=ExampleForm())
3.6 搜索框
- 表单对象
class Search(FlaskForm):LIST=[('','不限'),('A','A'),('B','B'),('C','C'),('D','D'),('E','E'),]grade=SelectField(render_kw={'class': 'grade'},choices=LIST)name=SearchField(render_kw={'class': 'name','placeholder':'企业名'})查询 = SubmitField()
- 视图函数
#app.py@app.route('/', methods=['GET', 'POST'])
def index():#获取查询对象company=companyInfo.queryif request.method=='GET':s=Search(request.args)name=request.args.get('name','')grade=request.args.get('grade','')else:s=Search(request.form)name=request.form.get('name','')grade = request.form.get('grade','')if grade!='':company=company.filter(companyInfo.等级==grade)if name!='':company=company.filter(companyInfo.name.like(f'%{name}%'))#分页page = request.args.get('page', 1, type=int)pagination = company.paginate(page=page, per_page=20)messages = pagination.items#表头titles = [ ('id', '#'),('name', '企业名'), ('法人', '法人'), ('类型', '类型'), ('等级', '等级')]return render_template('index.html', pagination=pagination, messages=messages, companyInfo=companyInfo, titles=titles,Search=s,name=name,grade=grade)
- 模板
{% from 'bootstrap4/form.html' import render_form %}
{{ render_form(Search,'/') }}
四、Ajax
4.1 定义
异步 JavaScript 和 XML,或 Ajax 本身不是一种技术,而是一种将一些现有技术结合起来使用的方法,包括:HTML 或 XHTML、CSS、JavaScript、DOM、XML、XSLT、以及最重要的 XMLHttpRequest 对象。当使用结合了这些技术的 Ajax 模型以后,网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。
尽管 Ajax 中的 X 代表 XML,但是 JSON 才是首选,因为它更加轻量,而且是用 JavaScript 编写的。在 Ajax 模型中,JSON 和 XML 都被用来包装信息。
4.2 jQuery Ajax语法
$.ajax({name:value, name:value, ... })
4.3 jQuery Ajax函数参数
名称 | 值/描述 |
---|---|
async | 布尔值,表示请求是否异步处理。默认是 true。 |
beforeSend(xhr) | 发送请求前运行的函数。 |
cache | 布尔值,表示浏览器是否缓存被请求页面。默认是 true。 |
complete(xhr,status) | 请求完成时运行的函数(在请求成功或失败之后均调用,即在 success 和 error 函数之后)。 |
contentType | 发送数据到服务器时所使用的内容类型。默认是:“application/x-www-form-urlencoded”。 |
context | 为所有 AJAX 相关的回调函数规定 “this” 值。 |
data | 规定要发送到服务器的数据。 |
dataFilter(data,type) | 用于处理 XMLHttpRequest 原始响应数据的函数。 |
dataType | 预期的服务器响应的数据类型。 |
error(xhr,status,error) | 如果请求失败要运行的函数。 |
global | 布尔值,规定是否为请求触发全局 AJAX 事件处理程序。默认是 true。 |
ifModified | 布尔值,规定是否仅在最后一次请求以来响应发生改变时才请求成功。默认是 false。 |
jsonp | 在一个 jsonp 中重写回调函数的字符串。 |
jsonpCallback | 在一个 jsonp 中规定回调函数的名称。 |
password | 规定在 HTTP 访问认证请求中使用的密码。 |
processData | 布尔值,规定通过请求发送的数据是否转换为查询字符串。默认是 true。 |
scriptCharset | 规定请求的字符集。 |
success(result,status,xhr) | 当请求成功时运行的函数。 |
timeout | 设置本地的请求超时时间(以毫秒计)。 |
traditional | 布尔值,规定是否使用参数序列化的传统样式。 |
type | 规定请求的类型(GET 或 POST)。 |
url | 规定发送请求的 URL。默认是当前页面。 |
username | 规定在 HTTP 访问认证请求中使用的用户名。 |
xhr | 用于创建 XMLHttpRequest 对象的函数。 |
4.4 基本Ajax请求方法
$.ajax({url: '接口url',dataType: "返回数据格式",type: "请求方法",success: function (data) {.....},error: function (err) {.....}})
五、echarts
ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE9/10/11,Chrome,Firefox,Safari等),底层依赖矢量图形库 ZRender,提供直观,交互丰富,可高度个性化定制的数据可视化图表。
官网Apache ECharts
5.1 简单demo
- HTML代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">#导入jquery和echarts的js文件<script src="../static/js/jquery-1.11.1.min.js"></script><script src="../static/js/echarts.min.js"></script>
</head>
<body>
#width和height必须设置
<div style="width: 600px;height: 400px"></div>
<script>#初始化图表对象,图表载入至divvar mCharts = echarts.init(document.querySelector("div"))var xData = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']var yData = [3000, 2800, 900, 1000, 800, 700, 1400, 1300, 900, 1000, 800, 600]#配置图表var option = {xAxis:{type:'category',data:xData},yAxis:{type:'value'},series:[{type:'line',data:yData,label:{show:true,rotate:0}}]}#显示图表mCharts.setOption(option)
</script>
</body>
</html>
- 效果
5.2 Echarts结合flask
- 视图函数
@app.route('/chart', methods=['GET', 'POST'])
def test_chart():xdata= ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']ydata=[3000, 2800, 900, 1000, 800, 700, 1400, 1300, 900, 1000, 800, 600]return render_template('echarts.html',xdata=xdata,ydata=ydata)
- 模板
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">#导入jquery和echarts的js文件<script src="../static/js/jquery-1.11.1.min.js"></script><script src="../static/js/echarts.min.js"></script>
</head>
<body>
#width和height必须设置
<div style="width: 600px;height: 400px"></div>
<script>#初始化图表对象,图表载入至divvar mCharts = echarts.init(document.querySelector("div"))#模板获取后端数据var xData = {{xdata |tojson}}var yData = {{ydata |tojson}}#配置图表var option = {xAxis:{type:'category',data:xData},yAxis:{type:'value'},series:[{type:'line',data:yData,label:{show:true,rotate:0}}]}#显示图表mCharts.setOption(option)
</script>
</body>
</html>
5.3 Echarts结合Ajax
- 视图函数
#后端设计api,返回json数据
@app.route('/api/analysis', methods=['GET', 'POST'])
def analysis():data={}try:data['list']=[]#这里有A、B、C、D、E五个等级,分别获取每个等级的企业数量for i in ['A','B','C','D','E']:data['list'].append({'count':companyInfo.query.filter(companyInfo.等级==i).count(),'等级':i})status=200msg='success'except Exception as e:status=500msg=f'{e}'datas={'data':data,'status':status,'msg':msg}return jsonify(datas)
- 接口返回的数据
{"data": {"list": [{"count": 161246,"等级": "A"},{"count": 20809,"等级": "B"},{"count": 237,"等级": "C"},{"count": 3558,"等级": "D"},{"count": 108,"等级": "E"}]},"msg": "success","status": 200
}
- js代码
//该处代码利用Ajax访问后端接口获取数据,获取成功就调用echarts进行绘图
$.ajax({url: '/api/analysis',dataType: "text",type: "get",success: function (data) {//将data解析为json对象(相当于python中的字典)var data=JSON.parse(data)['data']['list']var myChart = echarts.init(document.querySelector('#analysis'));option = {//表名title: {text: '评级分布图'},legend: {top: 'bottom'},tooltip: {trigger: 'item',formatter: '{a} <br/>{b} : {c} ({d}%)'},toolbox: {show: true,feature: {mark: { show: true },dataView: { show: true, readOnly: false },restore: { show: true },saveAsImage: { show: true }}},series: [{name: '评级分布',type: 'pie',radius: [70, 150],center: ['50%', '50%'],roseType: 'area',itemStyle: {borderRadius: 8},//将api获取的数据填入data: [{ value: data[0]['count'], name: data[0]['等级'] },{ value: data[1]['count'], name: data[1]['等级'] },{ value: data[2]['count'], name: data[2]['等级'] },{ value: data[3]['count'], name: data[3]['等级'] },{ value: data[4]['count'], name: data[4]['等级'] },]}]};//显示图表myChart.setOption(option);},error: function (err) {}})
- 效果