文武的客 - flask
type: channel
link: https://binscor.top/index.php/tag/flask/
items: 第9节、flask部署（虚拟机环境）
items: 第8节、Model02以及文件迁移
items: 第6节、扩展库的使用
items: 第7节、model01以及拆分MVT
items: 第5节、Flask表单
items: 第4节、模板引擎02
items: 第3节、模板引擎01
items: 第2节、Flask基础02
items: 第1节、Flask基础01

第9节、flask部署（虚拟机环境）
type: item
date: 2019-08-19T11:28:00+08:00
description: 一、安装1.安装ssh新版本安装位 apt/apt-get老版本为 apt-get安装以后 ifconfig查看当前的ip地址如果网络不在同一个ip段 将网络模式设置为桥接2.安装pip3sudo apt install python3-pip在要安装项目的目录创建虚拟环境virtualenv venvsource activate # 开启虚拟开发环境模式退出 deactivatepip3 install uwsgi # 安装uwsgi二、配置uwsgi配置文件支持很多格式，我采用.ini格式，命名为uconfig.ini具体内容如下：socket指出了一个套接字，相当于为外界留出一个uwsgi服务器的接口。[uwsgi] # 外部访问地址，可以指定多种协议，现在用http便于调试，之后用socket # socket = 0.0.0.0:8000 # uwsgi的监听端口 # 指向项目目录 chdir = /home/xlg/blog/ # flask启动程序文件 wsgi-file = manage.py # flask在manage.py文件中的app名 callable = app plugins = python# 这行一定要加上，不然请求时会出现-- unavailable modifier requested: 0 --错误提示 # 处理器数 processes = 1 # 线程数 threads = 2 #状态检测地址 #stats = 127.0.0.1:9191socket和http的差别。从概念上来说，socket本身不是协议而是一种具体的TCP/IP实现方式，而HTTP是一种协议且基于TCP/IP。具体到这个配置这里来，如果我只配了socket = 127.0.0.1:5051的话，通过浏览器或者其他HTTP手段是无法成功访问的。而在uwsgi这边的日志里会提示请求包的长度超过了最大固定长度。另一方面，如果配置的是http = 127.0.0.1:5051的话，那么就可以直接通过一般的http手段来访问到目标。但这会引起nginx无法正常工作。正确的做法应该是，如果有nginx在uwsgi之前作为代理的话应该配socket，而如果想让请求直接甩给uwsgi的话那么就要配httppythonpath指出了项目的目录，module指出了项目启动脚本的名字而紧接着的wsgi-file指出了真正的脚本的文件名。callable指出的是具体执行.run方法的那个实体的名字，一般而言都是app=Flask(__name__)的所以这里是app。processes和threads指出了启动uwsgi服务器之后，服务器会打开几个并行的进程，每个进程会开几条线程来等待处理请求，显然这个数字应该合理，太小会使得处理性能不好而太大则会给服务器本身带来太大负担。daemonize项的出现表示把uwsgi服务器作为后台进程启动，项的值指向一个文件表明后台中的所有输出都重定向到这个日志中去。daemonize = /home/wyz/flask/server.log三、安装 nginxsudo apt-get install nginxNginx是轻量级、性能强、占用资源少，能很好的处理高并发的反向代理软件。Ubuntu 上配置 Nginx 也是很简单，不要去改动默认的 nginx.conf 只需要将/etc/nginx/sites-available/default文件替换掉就可以了。 新建一个 default 文件:server{ listen 80; # 服务器监听端口 server_name 10.0.121.116; # 这里写你的域名或者公网IP location / { uwsgi_pass 127.0.0.1:8000; # 转发端口，需要和uwsgi配置当中的监听端口一致 include uwsgi_params; # 导入uwsgi配置 #uwsgi_param UWSGI_PYTHON /home/自己创建的目录/venv; # Python解释器所在的路径（这里为虚拟环境） uwsgi_param UWSGI_PYTHON /usr/bin/python3; uwsgi_param UWSGI_CHDIR /home/xlg/blog/;# # 自己创建的目录 项目根目录 uwsgi_param UWSGI_SCRIPT manage:app; # 指定启动程序 #比如你测试用test.py文件，文件中app = Flask(name)，那么这里就填 test：app } }服务启动sudo service nginx startsudo service nginx stopsudo service ng…

第8节、Model02以及文件迁移
type: item
date: 2019-08-19T11:27:00+08:00
description: 一、Model对数据的操作3种办法(1) 最原始的 提交 和 回滚#最原始的添加 提交或者回滚 每次都需要 @test.route('/insert_one/') def insert_one(): try: # u = User(username='zhangshang',sex=False,age=18) u = User('lisi',True,20) db.session.add(u) db.session.commit() except: db.session.rollback() return 'insert_one'注意：每次都需要提交和回滚(2) 在settings.py进行配置SQLALCHEMY_COMMIT_ON_TEARDOWN = True每次添加或者保存，修改，删除数据 都不需要commit() 或者 rollback()实例app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True #设置自动提交 #settings.py已经设置为数据自动提交 @test.route('/auto_insert_one/') def auto_insert_one(): u = User('王五',False,30) db.session.add(u) return 'insert_one'(3) 自定义增删改的基类 进行封装user.py中base类的书写class Base: #添加一条数据 def save(self): try: db.session.add(self) db.session.commit() except: db.session.rollback() #添加多条数据 @staticmethod def save_all(*args): try: db.session.add_all(args) db.session.commit() except: db.session.rollback() #自定义删除基类 def delete(self): try: db.session.delete(self) db.session.commit() except: db.session.rollback()user.py中base类的使用class User(Base,db.Model): __tablename__ = 'user' id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(12),index=True) sex = db.Column(db.Boolean,default=True) age = db.Column(db.Integer,default=20) icon = db.Column(db.String(40),default='default.jpg') def __init__(self,username,sex=True,age=18,icon='default.jpg'): self.username = username self.sex = sex self.age = age self.icon = icon蓝本文件中的使用#使用自定义的base类 进行添加 自带提交和回滚 @test.route('/self_insert_one/') def self_insert_one(): u = User('兆六',False,20) u.save() return 'insert_one' #添加多条数据 @test.route('/self_insert_many/') def self_insert_many(): sex = [True,False] u1 = User(random.randrange(1000,10000),sex[random.randint(0,1)],random.randint(1,100)) u2 = User(random.randrange(1000,10000),sex[random.randint(0,1)],random.randint(1,100)) User.save_all(u1,u2) return '添加多条' #自定义删除方法的使用 @test.route('/delete/') def delete(): u = User.query.get(2) u.delete() return '删除' #自定义修改方法的使用 @test.route('/update/') def update(): u = User.query.get(2) u.username = '…

第6节、扩展库的使用
type: item
date: 2019-08-19T11:26:00+08:00
description: 一、flash消息的显示概述： 当用户状态发生改变等等的处理时， 需要给用户显示出提示信息 flash就是实现这个功能的导入： from flask import flash,get_flashed_messagesflash 存数据get_flashed_messages() 获取flash存储的数据实例manage.py#ajax处理登录的视图 @app.route('/do_login/',methods=['POST']) def dologin(): # print(request.args.get('username')) username = request.form.get('username') userpass = request.form.get('userpass') if username == 'zhangsan': if userpass == '123456': flash("登录成功") # flash("登录成功2") # flash("登录成功3") # print(get_flashed_messages()) data = {'code':200} else: data = {'code':400} else: data = {'code':404} return jsonify(data)base.html{% for message in get_flashed_messages() %} × Warning! {{ message }} SS {% endfor %}二、flask-moment 时间显示的扩展库概述： 专门负责时间的显示 可以显示当前时间 可以计算时间的差值附：用法导入：from flask_moment import Momentmanage.pyfrom flask_moment import Moment #时间模块 from datetime import datetime,timedelta #导入时间模块 moment = Moment(app) manager = Manager(app) @app.route('/') def index(): nowtime = datetime.utcnow()+timedelta(seconds=-60) #前60秒的时间 return render_template('index.html',nowtime=nowtime)index.html 首页 {{ nowtime }} {{ moment(nowtime).format('L') }} {{ moment(nowtime).format('LL') }} {{ moment(nowtime).format('LLL') }} {{ moment(nowtime).format('LLLL') }} {{ moment(nowtime).format('YYYY-MM-DD') }} {{ moment(nowtime).fromNow() }} {% endblock %} {% block scripts %} {{ super() }} {{ moment.include_moment() }} #导入moment显示的js代码 {{ moment.locale('zh-CN') }} #格式化中国的时间 {% endblock %}三、文件上传1.原生文件上传(1)简单上传manage.py@ys.route('/form/',methods=['GET','POST']) def form(): # if request.method == 'POST' and request.files.get('photo'): if request.method == 'POST' and 'photo' in request.files: # print(request.files) #获取传递过来的文件 file = request.files.get('photo') #获取文件名称 filename = file.filename #存储上传的路径和名字 file.save(os.path.join(os.getcwd(),'static/upload/'+filename)) return 'ok' return render_template('ysfile/form.html')form.html 文件上传 附：python生成随机图形验证码(2)添加条件判断的上传manage.pyfrom flask import Blueprint,render_template,request,current_app import string…

第7节、model01以及拆分MVT
type: item
date: 2019-08-19T11:26:00+08:00
description: 一、Modelflask作为一款MVT的框架，也具有ORM模型的操作，通过扩展库(flask-sqlalchemy)来实现。随着项目越来越大，采用原生sql的话，就会出现大量的原生sql语句。ORM模型的好处：SQL语句重复使用率低，越复杂的sql语句，语句就越长，会出现很多相似的sql语句很多sql语句都是根据业务逻辑拼接出来的，如果数据库发生了修改，那么这些逻辑就需要重写 这样就会漏掉某些sql的更改原生SQL容易漏掉，对sql语句安全性的考虑工作原理：ORM 是对象关系的映射，我们可以通过类的方式去操作数据库，不再使用原生的SQL语句了。ORM中的类映射数据库中的每个表，类中的每个属性映射成表中的每个字段。ORM最终还是会将开发者操作的增删改查的代码转换成sql语句，再去操作数据库。好处：可以使用简短的代码写出比较复杂的SQL语句可以减少重复sql语句的概率可移植性好，只需要更改settings.py的配置sqlite,mysql等二、原生SQL(1) 创建数据库 python1807create database if not exists python1807 character set utf8;(2) 安装pymysql模块pip install pymysql(3) 安装flask-sqlalchemypip install flask-sqlalchemy(4) 配置链接数据库的URI地址#配置链接数据库的URI地址 HOST = '127.0.0.1' USER = 'root' PASSWORD = '123456' PORT = '3306' NAME = 'python1807' DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USER,PASSWORD,HOST,PORT,NAME)实例from sqlalchemy import create_engine #配置链接数据库的URI地址 HOST = '127.0.0.1' USER = 'root' PASSWORD = '123456' PORT = '3306' NAME = 'python1807' DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USER,PASSWORD,HOST,PORT,NAME) #创建sqlalchemy操作数据库引擎 engine = create_engine(DB_URI) with engine.connect() as con: con.execute('drop table user ') con.execute('create table user(id int,username varchar(10))') con.execute('drop table user ') #在windows下 库，表名 不区分大小写 linux下 严格区分大小写三、flask-sqlalchemy Model(1) 导入from flask-sqlachemy import SQLAlchemy(2) 配置URI地址app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@127.0.0.1:3306/python1807' #配置链接数据库的地址四、model的字段 可选项(1) 字段类型类型名python类型说明Integerint整形 2(10）SmallIntegerint小整形BigerIntegerint长整形Floatfloat浮点形Stringstringvarchar类型 0-255Textstringtext 类型 0-65535BooleanboolTrue FalseDatedatetime.date日期Timedatetime.time时间DateTimedatetime.datetime日期和时间(2) 约束条件选项说明primary_key主键索引unique唯一索引index常规索引nullable是否为空 默认Truedefault默认值五、创建模型配置from flask import Flask from flask_script import Manager from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@127.0.0.1:3306/python1807' #配置链接数据库的地址 app…

第5节、Flask表单
type: item
date: 2019-08-19T11:25:00+08:00
description: 一、原生表单1. 添加模板文件login.html，内容如下： 用户名： 2. 视图函数，如下：# 登录 @app.route('/login/') def login(): return render_template('login.html') P # 校验 @app.route('/check/', methods=['POST']) def check(): print(request.form.get('username')) return 'Hello %s !' % request.form['username']3. 将登录页面和校验的路由合并，如下：@app.route('/login/', methods=['GET', 'POST']) def login(): if request.method == 'GET': return render_template('login.html') else: return 'Hello %s !' % request.form['username']一个路由处理时，表单的action属性不用书写，默认提交到当前路由。二、flask-wtf处理表单说明：flask-wtf是一个用于表单处理的扩展库，提供了CSRF、校验等功能，使用非常方便附：flask-wtf教程1.跨站请求伪造保护(csrf)附：浅谈CSRF攻击方式Flask-WTF 能保护所有表单免受跨站请求伪造(Cross-Site Request Forgery,CSRF)的攻击。恶意网站把请求发送到被攻击者已登录的其他网站时就会引发 CSRF 攻击。为了实现 CSRF 保护,Flask-WTF 需要程序设置一个密钥。Flask-WTF 使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。#视图中 设置 Flask-WTF app = Flask(__name__) app.config['SECRET_KEY'] = 'hard to guess string'#字典可用来存储框架、扩展和程序本身的配置变量。 #为了增强安全性,密钥不应该直接写入代码,而要保存在环境变量中。 #模板中使用 {{ form.hidden_tag() }} #或 {{ form.csrf_token }}2.关闭csrf@app.route('/form/',methods=['post','get']) def newform(): form = NameForm(csrf_enabled = False)3.flask-wtf常见字段类型和验证器常见字段类型字段类型说明StringField普通文本字段SubmitField提交按钮PasswordField密码文本字段HiddenField隐藏文本字段TextAreaField多行文本字段DateField文本字段，datetime.date格式DateTimeField文本字段，datetime.datedatime格式IntegerField文本字段，值为整数FloatField文本字段，值为小数BooleanField复选框，值为True或FalseRadioField单选框SelectField下拉框FileField文件上传常见验证器类验证器说明DataRequired确保字段有值 必填项Email邮箱地址 验证邮箱IPAddressIP地址Length规定字符长度 有min和max两个值进行限制。NumberRange输入数值的范围EqualTo验证两个字段的一致性URL有效的URLRegexp正则验证info = TextAreaField('个人信息',render_kw={'style':'resize:none;'}) #render_kw 给当前的标签添加属性表单类每个 Web 表单都由一个继承自Form的类表示。这个类定义表单中的一组字段（表单的内容与类的字段是一一对应的）,每个字段都用对象（表单中的对象）表示。字段对象可附属一个或多个验证函数。4.定义表单类# 导入表单基类 from flask_wtf import FlaskForm # 导入字段类型 from wtforms import StringField, SubmitField # 导入验证器类 from wtforms.validators import DataRequired #必填字段 # CSRF需要使用 app.config['SECRET_KEY'] = '123456' # 定义表单类 class NameForm(FlaskForm): #name 为表单的name名称 name = StringField('用户名', validators=[Data…

第4节、模板引擎02
type: item
date: 2019-08-13T15:22:00+08:00
description: 一、macro 宏的使用概述： 类似于python中的函数(1)主体结构{ % macro 宏名称([参数...]) % } ... { % endmacro % } {{ 宏名称([参数...]) }}实例{ % macro form(textname,text='text',name='',value='') % } {{ textname }} { % endmacro % } {{ form('用户名：',name='username') }} {{ form('密码：','password','userpass') }} {{ form('','submit',value='submit') }} (2)导入macrocommon/public_macro.htmlfrom ... import ... as ..{ % from 'common/public_macro.html' import form % } { % from 'common/public_macro.html' import form as f % } #起别名fimport ... as{ % import 'common/public_macro.html' as mymacro % }注意：宏的调用 必须在定义的下方来调用如果有形参且没有默认值则可以不传实参参数默认从左到右依次对应形参默认值 遵循默认值规则 （有默认值的放在右侧）关键字参数的使用 一样当导入的包名字过长，或者是当前文件中存在同名的变量或者函数,类名 为防止重名覆盖 使用 as 起别名二、模板继承1. extends格式：{ % extends '模板路径/模板名称.html' % }2. block对于父模板的代码的替换实例base.html(父模板) { % block head % } { % block meta % } { % endblock % } {# { % block title % }{{ title|default('base') }}{ % endblock % } #} { % block title % }base{ % endblock % } { % block link % } { % endblock % } { % block script % } { % endblock % } { % endblock % } 导航 { % block con % } { % endblock % } 底部栏 child.html(子模板){ % extends 'common/base.html' % } { % block title % } child { % endblock % } { % block style % } { { super() } } a{display:block;width:200px;height:200px;color:white;background-color:yellow;} a:hover{background-color:blue;} div{background-color:green;} { % endblock % } { % block con % } 我是子模板的内容部分 点击去百度 { % endblock % }注意： 如果子模板继承了父模板后代码缺失或者样式不起作用，查看是否调用了{ { super () } }，super调用父模板中被替换掉的代码和样式三、在flask中使用bootstrap(flask-bootstrap)(1)创建bootstrap模板对象from flask_bootstrap import Bootstrap app.config['BOOTSTRAP_SERVE_LOCAL'] = True #加载本地的bootstrap样式 否则从网络请求 bootstrap = Bootstrap(app)(2)使用flask-bootstrap的base模板{ % block doc -% } <html{ % block html_attribs % }{ % endblock html_attribs % }> { %- block html % } { %- block head % } { % block title % }{{title|default}}{ % endblock title % } { %- block metas % } { %- endblock metas % } { %- block styles % } { %- endblock styles % } { %- endblock head % } <body{ % block…

第3节、模板引擎01
type: item
date: 2019-08-08T16:46:00+08:00
description: 一、模板简介概述： 模板就是按照一定的规则书写的负责展示的html页面，模板引擎提供特定规则、替换的工具。模板引擎：jinja2目录结构project/ templates/ #推荐使用该文件名，使用其他的名称需重新配置 manage.py模板渲染使用的方法(1)render_template(template_name,**context)响应一个html模板(2)render_template_string响应一段html代码 （适合响应简短的样式的响应）二、模板中语法的分类1. 变量 {{ 变量名称 }}视图传递给模板的数据遵循变量/标识符的命名规则关键字参数实例 可以给render_template 添加关键字参数,进行变量的传递@tem.route('/test/') def test(): h1con = '模板的变量' return render_template('test.html',h1=h1con) #渲染模板响应给用户 模板中使用 {{ h1 }} 注意： 如果给定的变量不存在则什么都不插入（什么都没有）2. 标签 {% 标签名称 %}就是python中的逻辑的判断循环/if...三、过滤器（相当于python中的函数）过滤器使用管道符 | 添加上函数和值进行使用abs 返回一个数值的绝对值default 默认值 注意： 默认只有当前变量不存在才执行默认值，将参数boolean改为True，则bool和undefined都执行默认值实例 boolean默认为Falsefirst 返回序列中的第一个元素last 返回序列中的最后一个值format 格式化输出{{ "我叫%s 我今年%d岁了 我的存款为%.2f元"|format('张三',18,123) }}length 值长度join 拼接{{ ['a','b','c']|join('') }} safe 对视图传递的html代码进行转义解析 （默认不解析 转义掉）int 转换整形float 浮点string 字符串list 转换成列表upper 转换成大写lower 转换成小写replace 替换 {{ 'abcd'|replace('a','x') }}striptags 取出html标签trim 去除两侧空格四、标签语法格式：{% %} 注意： 标签有开始，就要有结束> < >= <= == != in not in and or(1) if elif else{% if 90<=data.grade<=100 %} 优秀 {#{% elif 80<=data.grade<=89 %}#} {% elif 80<=data.grade %} 良 {#{% elif 70<=data.grade<=79 %}#} {% elif 70<=data.grade %} 中 {% else %} 还可以 {% endif %}(2) for 循环{% for ... %}​ ...{% endfor %}迭代字典{% for k,v in data.items() %} {{ k }}----{{ v }} {% endfor %} {% for i in range(10) %} {{ i }} {% endfor %}搭配else{ % for i in abc % } {{ i }} { % else % } 执行else了 { % endfor % }注意： 当迭代的变量不存在则执行else获取当前迭代的状态变量说明loop.index当前迭代的索引 从1开始loop.index0当前迭代的索引 从0开始loop.first是否为第一次迭代loop.last是否为最后一次迭代loop.length迭代的长度注意： 没有break 和 continue五、注释多行注释{# 注释的内容 #}注意： 多行注释不能嵌套多行注释六、文件的包含 include概述：include语句可以把一个模板导入到另外的一个模板的指定位置，就相当于把另外的模板中的代码粘贴到了你的指定位置结构：{% include 路径/模板名称.html %}实例文件目录 project/ templates/ commom/ header.html footer.html index.html manage.pymanage.py@app.route('/') def index(): return render_template('index.html') #跳到首页模板common/header.html 导…

第2节、Flask基础02
type: item
date: 2019-08-07T08:21:00+08:00
description: 一、flask-script扩展库简介：是一个flask终端运行的解析器，因为在项目完成以后 所有的代码都不应该有任何的修改 因为一旦有修改 就有可能带来bug导入： from flask_script import Manager使用from flask_script import Manager manager = Manager(app) ... if __name__ == '__main__': manager.run()启动的参数参数参数说明-h帮助-h主机-p端口号-d调试 显示出现的错误信息-r代码加载--threaded开启多线程在控制台输入启动命令运行程序python3 manage.py runserver -hpython3 manage.py runserver -h0.0.0.0 -p5000 -d -r --threaded #全部开启python3 manage.py runserver -d -r #开启调试和代码加载二、蓝本/蓝图（blueprint）概述：当项目的代码越来越多的时候 把所有代码 都放到一个文件中 是不合理的 要根据不同功能的视图函数 进行划分到不同的模块文件中使用新建一个user.pyfrom flask import Blueprint #导入蓝本 user = Blueprint('user',__name__) #参数1 当前蓝本的名字 参数2 所在模块 @user.route('/loign/') def login(): return 'login'在manage.py中注册蓝本,使之与当前的flask框架关联起来from user import user #从user.py模块中 导入user蓝本对象 app.register_blueprint(user) #注册蓝本 #http://127.0.0.1:5000/login/ app.register_blueprint(user,url_prefix='/user') #添加一个路由前缀 http://127.0.0.1:5000/user/login/蓝本之间的重定向from flask import Blueprint,url_for,redirect user = Blueprint('user',__name__) #实例化蓝本对象 参数1 为蓝本的名字 参数2为所在的模块 @user.route('/login/') def login(): # return '蓝本登录' return redirect(url_for('posts.send_posts')) #指定跳转到对应的蓝本的视图函数中三、当前flask对象的代理对象(current_app)获取app对象上的所有的配置app = Flask(__name__) #添加配置俩种方式 app.config['SECRET_KEY'] = '123' #给flask 添加了一个配置 secret_key app.name = 'zhangsan' #给flask 添加了一个配置 secret_key manager = Manager(app) #实例化并加载app获取配置信息from flask import Blueprint,current_app posts = Blueprint('posts',__name__) #获取配置的两种方式 @posts.route('/send_posts/') def send_posts(): # return '发帖子{}'.format(current_app.config['SECRET_KEY']) #获取secret_key的值 return '发帖子{}'.format(current_app.name) #获取name的值四、cookie 和 session附：cookie和session的区别和用法1.cookie原因： http协议 无状态协议在网站中，http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后，第二次请求服务器依然不能知道当前请求是哪个用户。cookie的出现就是为了解决这个问题，第一次登录后服务器返回一些数据（cookie）给浏览器，然后浏览器保存在本地，当该用户发送第二次请求的时候，就会自动的把上次请求存储的cookie数据自动的携带给服务器，服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie存储的数据量有限，不同的浏览器有不同的存储大小，但一般不超过4KB。因此使用cookie只能存储一些小量的数据。(1) 设置cookieResponse.set_cookie( key, 键 value,值 max_age=None, #存活…

第1节、Flask基础01
type: item
date: 2019-08-06T18:10:00+08:00
description: Flask框架学习的整体内容1.Flask基础2.模板引擎3.flask表单4.文件上传5.邮件发送6.模型(model)7.拆分MVT8.项目的需求分析(博客)9.Flask项目10.flask部署11.flask-resfulFlask web框架分为MVCM: 模型 （数据的操作）V : 视图C : 控制器python中 MVTM: 模型 （数据的操作）V : 控制器T: 视图web 架构B/S浏览器/服务器C/S客户端/服务器Flask模块概述： flask是一个非常小的python web框架，被称为微型框架，只提供了一个强健的核心 ，其它功能都是通过第三方扩展库来实现的。组成： 路由、模板、模型、控制器、wsgi系统、jinja2模板引擎一、完整的运行(1) 实例from flask import Flask #导入Flask app = Flask(__name__) #实例化flask类 __name__ 必传参数 当前执行的模块 #路由地址 请求当前的路由 127.0.0.1：5000 @app.route('/') def index(): #执行请求的函数 控制器 return 'hello flask' #响应 响应一段字符串 if __name__ == '__main__': #执行的模块 只在主程序执行 app.run() #运行flask(2) 路由地址@app.route('/地址/')def 函数名称([参数...]):​ pass请求地址为：http://ip地址:端口号/地址/(3) app.run参数参数参数说明debug是否开启调试模式 默认False 开启以后自动重新加载代码threaded开启多线程 默认是不开启的 Truehost主机名 默认是127.0.0.1 在其它反问的时候 127.0.0.1-127.255.255.254 本地ip 0.0.0.0本地，网络都可以请求port端口号 默认5000实例：if name == 'main': #执行的模块 只在主程序执行 app.run( host='0.0.0.0',port=5001,debug=True,threaded=True) #运行flaskhttp://10.0.121.138:5001/http://127.0.0.1:5001/二、视图函数(1) 无参路由@app.route('/') def index(): pass(2) 带一个参数的路由#传递一个参数的路由 @app.route('/args/<page>/') def args(page): print(type(page)) return 'page的值为{}'.format(page)注意： 路由值都为字符串类型(3) 传递多个参数#传递多个参数 类型1： #http://127.0.0.1:5000/manyarg/1/2/ @app.route('/manyarg/<arg1>/<arg2>/') def manyArg(arg1,arg2): print(type(arg1),type(arg2)) return 'arg1的值为{} arg2的值为{}'.format(arg1,arg2) #传递多个参数 类型2： #http://127.0.0.1:5000/manyarg/1_2/ @app.route('/manyarg/<arg1>_<arg2>/') def manyArg(arg1,arg2): print(type(arg1),type(arg2)) return 'arg1的值为{} arg2的值为{}'.format(arg1,arg2) #运行结果：arg1的值为1 arg2的值为2(4) 限制参数的类型intstringpathfloat@app.route('/argtype/<int:arg>/') #只能传递整形 @app.route('/argtype/<string:arg>/') #字符串 默认就是字符串 @app.route('/argtype/<path:arg>/') #路径 将/不再认为是分隔符 而是值的一部分 其实也是字符串类型 @app.route('/argtype/<float:arg>/') #浮点形 def argType(arg): print(type(arg)) print(arg) return '参数类型'注意：路由地址末尾的‘/’ 建议都加上，如果在访问需要‘/’的路由的时候没有添加‘/’的话，浏览器会自动添加上‘/’参数写在<>内，<>内的参数和前面的路由地址构造出一个全新的路由地址参数类型默认为 string三、响应 response(1) 指定响应的状态码实例@a…