FLASK 一、概述 flask是一个基于python并依赖于Jinja2模板引擎和WerkZeug WSGI(Web Server Gatewey InterFace.web)服务的框架 WSGI:服务网关接口,提供处理网络请求相关的功能 hello world from flask import Flask # 创建flask的程序实例 app = Flask(__name__) @app.route('/') # 路由配置 # 视图函数 def index(): return "

欢迎访问

" # 启动服务 if __name__ == "__main__": app.run(debug=True) 二、 定义路由 路由是为了匹配用户的请求地址,会自动执行视图函数。视图函数中必须有返回值,返回字符串显示到响应的页面中。 2. 无参数 定义路由 @app.route('/地址') 定义视图函数 def funcName(): return "" # 响应到页面的内容 例如: @app.route("/") # '/'表示根路径 def index(): #匹配到路径后执行的视图函数 return "首页" 3. 带参数 变量:<变量名> @app.route("/login/") def login(name): return "欢迎%s登陆"%name 如需要设置默认路由,则在视图函数中传参直接设置def login(name="Chancey") 还有一种方式,就是在路由装饰器中传入一个字典@app.route("/login/",defaults={"name":"游客"}) 4. 类型转换器 缺省:字符串,不能包含'/' int:转换整数 float:转换小数 path:字符串,运行包含'/' 使用:@app.route('/show/')在路径中直接转换 例如 配置路由:/calaute//,视图函数中接收参数,返回类似于“3 + 5 = 8” @app.route('/calaute//') def calaute(num1,num2): return "%s + %s = %d"%(num1,num2,int(num1)+int(num2)) 注意:路径中的参数变量永远是字符串 5. 多个URL 多个URL执行同一个视图函数 @app.route("/") @app.route("/index") def index(): return "首页" 例如 定义路由:127.0.0.1:5000/show 127.0.0.1:5000/show/list 127.0.0.1:5000/show/,执行同一个函数,返回相应的内容 @app.route("/show") @app.route("/show/list") @app.route("/show/") def show(name="Chancey"): return "show %s"% name 如果在app.run()设置host=0.0.0.0 不影响当前虚拟IP(127.0.0.1) 可以让当前局域网中的其他计算机通过内网IP访问服务器 二、模板 模板是一种特殊的HTML文件,Python+HTML网页结构,允许在模板文件中使用变量,定义流程控制。使用模板可以使用视图函数专注于处理业务逻辑,将页面渲染交由模板控制 导入render_template 项目中创建“templates”文件夹,所有模板文件必须存放"template"文件夹下 在视图函数中使用render_template("模板文件"),生成模板字符串,交由浏览器解析 from flask import Flask,render_template app = Flask(__name__) @app.route("/info") def info(): return render_template("01-show.html", name="flask", age=20) 1. 变量代码块 模板中使用变量 语法:{{ 变量名(key) }} 从视图函数中获取相关的变量,传递到模板文件中 语法:return render_template("模板文件", key1=value1, key2=value2) 函数中可以传递若干键值对,其中的key名就是在模板文件中使用的变量名 local()函数,是将当前作用域中的所有局部变量打包成一个字典返回,可以用一个变量接收,然后传递到模板中. 如果变量里面有字典类型的数值,有两种方法取值variable["keyName"]、variable.keyName) 如果变量里面有列表类型的数值,则直接用list[number]取值 例如: 视图函数中定义变量(name="" age= dic= tub= list= ),将数据传递到模板文件中显示 from flask import Flask, render_template # 创建实例 app = Flask(__name__) # 定义动物类 class Pet(object): name = None def play(self): return "来和" + self.name + "玩耍吧" @app.route('/show') def show(): name = "Chancey" age = 18 dic = { "name":"Waller", "age":20 } list = ["开车","保健"] tup = ("波多","仓井","海翼") # 实例化对象 cat = Pet() cat.name = "妲己" # locals() 将当前作用域中的局部变量包装成一个字典返回 # key=value return render_template("01-show.html", d=locals()) show

模板文件

列表、元组、字典都可以使用[key/index]和点语法访问

name:{{ d["name"] }}

age:{{ d.age }}

name:{{ d.dic["name"] }}

宠物名:{{ d.cat.name }}

动作:{{ d.cat.play() }}

2. 过滤器 允许模板中的变量在输出之前修改成其他的值,修改显示 upper转大写字母 lower转小写字母 title首字母大写 first获取第一个 last获取最后一个 length获取列表长度 default如果变量未赋值,可采用默认值 trim去掉字符串两边的空格 .... 语法:{{ 变量|过滤器1|过滤器2 }}

原版:{{ d.s1 }}

大写:{{ d.s1|upper }}

小写:{{ d.s1|lower }}

首字母大写:{{ d.s1|title }}

获取第一个:{{ d.s1|first }}

获取最后一个:{{ d.s1|last }}

获取长度:{{ d.s1|length }}

去掉两边空格:{{ d.s1|trim }}

未赋值的变量:{{ d.s2|default("默认变量") }}

3. 控制代码块 在模板中书写条件语句和循环语句,使用{% python语句 %} 3.1 if {% if 条件 %} 条件成立时。允许书写静态标签,也可以书写变量 {% endif %} {% if 条件 %} 条件成立时执行 {% else %} 条件不成立时执行 {% endif %} {% if 条件1 %} pass {% elif 条件2 %} pass {% elif 条件3 %} pass {% endif %} 例如: {% if d.age < 18 %}

{{ d.age }}岁未成年

{% elif d.age < 30 %}

{{ d.age }}岁青成年

{% elif d.age < 50 %}

{{ d.age }}岁中成年

{% else %}

{{ d.age }}岁老年人

{% endif %} 3.2 for {% for 变量 in 可跌对象 %} {% endfor %} show {% for item in info %} {% endfor %}
姓名 年龄
{{ item.name }} {{ item.age }}
from flask import Flask, render_template app = Flask(__name__) @app.route('/') def show(): info = [ {"name":"Chancey","age":18}, {"name":"Waller","age":35}, {"name":"Mary","age":16}, {"name":"Jacob","age":40}, {"name":"William","age":17}, {"name":"Samuel","age":37}, {"name":"Anthony","age":35}, ] return render_template("02-show.html", info=info) if __name__ == '__main__': app.run(debug=True, host="0.0.0.0") 3.3 loop 循环的内部变量loop:直接在内部使用,表示本次循环相关的信息 常用属性: loop.index当前循环的次数,默认从1开始计算 loop.index0当前循环的次数,从0开始计算 loop.first是否为第一次循环,值为True表示第一次循环 loop.last是否为最后一个循环 实例在前边for循环中已使用 4. 静态文件 不与服务器交互的文件都是静态文件(css、js、图片、音频等) 所有静态文件都必须存储在一个名为static的文件夹下,Flask程序会自动查找 静态文件的访问:必须使用/static访问 url_for("视图函数名")实现反向解析路由,后边可以跟参数 url_for("login")根据视图函数解析对应的URL url_for("login", uname="chancey", passwd="123456")反向解析带参数的路由 /login/chancey/123 /static/css/base.css 父模板 {% endblock %} 子模板中继承父模板 {% extends 父模板名称 %} 子模板中可以重写父模板中指定的块的内容 {% block 块名 %}

子模板

{% endblock %} {% block web_title %} 父模板 {% endblock %}

{% block title %} 这里是标题 {% endblock %}

{% block content %} 这里是内容 {% endblock %}

{% extends "02-base.html" %} {% block web_title %} 佛曰 {% endblock %} {% block title %} 佛曰 {% endblock %} {% block content %} 写字楼里写字间,写字间里程序员; 程序人员写程序,又拿程序换酒钱。 酒醒只在网上坐,酒醉还来网下眠; 酒醉酒醒日复日,网上网下年复年。 但愿老死电脑间,不愿鞠躬老板前; 奔驰宝马贵者趣,公交自行程序员。 别人笑我忒疯癫,我笑自己命太贱; 不见满街漂亮妹,哪个归得程序员? {% endblock %} 三、网络请求 利用网络通信协议实现前后端数据交互,常用的网络通信协议:HTTP(S),规定数据的传输格式 1. 请求 1.1 请求消息 客户端向服务端发送的消息 1.2 组成 请求起始行 协议、请求方式、资源路径 请求消息头 使用kry-value字典的方式存储相关信息 请求主体 get请求如果携带数据,以参数的形式直接拼接在URL后边(?key1=value1&key2=value2) 只有POST方式才会有请求主体 2. 响应 2.1 响应信息 服务端接收到请求并且处理之后,返回给客户端的信息(数据) 2.2 组成 响应起始行 协议、响应状态码、原因短句 响应消息头 描述响应回来的数据,以key:value存储 响应主体 保存响应数据 四、Flask中的HTTP 1. requests 在requests对象中封装了所有跟当前请求相关的信息 使用: 引入:from flask import request 使用:在视图函数中获取request对象内部的信息 属性: scheme获取此次请求的协议 method获取请求方式 args获取GET提交的数据 form获取POST提交的数据 cookies获取cookies中保存的数据 files获取上传的文件 path获取请求的资源路径(无参数) full_path获取请求的资源路径(携带参数) url 获取完整的请求地址 headers

子模板

协议:{{ params.scheme }}

请求方式:{{ params.method }}

请求的参数:{{ params.args }}

请求的参数的内容:{{ params.args.uname }}

请求的参数的内容:{{ params.args.age }}

cookies:{{ params.cookies }}

资源路径:{{ params.path }}

资源路径:{{ params.full_path }}

获取请求中的数据 获取GET请求中的数据 request.args["key"] request.args.get("key","默认值") request.args.getlist("key")适用于一个key对应多个值的情况(复选框) print(request.args.get("uname")) print(request.args.get("passwd")) print(request.args.getlist("hobby")) #get当时如果未携带数据,在视图函数中直接读取request.args['']数据,报400 获取POST请求中的数据 request.form获取数据字典 ​ request.form["key"] ​ request.form.get("key") ​ request.form.getlist('key') post即使未携带参数,直接获取字典的值,返回为空 页面重定向 由服务器端通知浏览器重新向新的地址发送请求 引入redirect 使用函数redirect("重定向地址") 视图函数中返回return redirect("重定向地址") 页面源 当前的请求是从哪一个源地址发起的,保存在请求消息头中("Referer":"") 文件上传 使用表单控件type="file"向服务器发送文件,因为文件,图片,音频等都是为禁止数据,必须设置表单的提交方式和编码类型
服务器端使用request.files获取上传的文件,返回字典 例如: f = request.files["key"] f.save(保存路径) @app.route("/add", methods=["GET", "POST"]) def add(): if request.method == "GET": return render_template("02-add.html") else: title = request.form["title"] type = request.form["type"] content = request.form["content"] print("标题:%s 类型:%s 内容:%s"%(title, type, content)) # 判断文件上传 if "userimg" in request.files: file = request.files["userimg"] file_name = generate_filename(file.filename) up_path = generate_upload_path(__file__, "static/upload", file_name) print("保存路径:" + up_path) return "获取数据成功" else: return "已存在" 2. response 模型(Models) 模型:根据数据表结构而创建出来的class(一张表一个类,一个字段就是一个属性) 框架:ORM(Object Relational Mapping 对象关系映射) 特征: 数据表到编程类的映射 数据类型的映射 关系映射(将数据库中表与表之间的关系 对应到 编程语言中类与类的关系) 优点: 封装操作提升效率 省略庞大的数据访问层 五、ORM 1. SQLAlchemy 安装:pip install flask-sqlalchemy 导包:from flask_sqlalchemy import SQLAlchemy 配置数据库:app.config['SQLALCHEMY_DATABASE_URI']="MYSQL://用户名:密码@数据地址:端口/数据库名" 创建数据库:create database dbname default charset utf8 collate utf8_general_ci; 数据库自动提交:app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True 映射 from flask import Flask from flask_sqlalchemy import SQLAlchemy # import pymysql # pymysql.install_as_MySQLdb() app = Flask(__name__) #连接数据库 app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:Asd.1234@127.0.0.1:3306/flaskDB" #创建SQLAlachemy实例 db = SQLAlchemy(app) print(db) if __name__ == '__main__': app.run(debug=True, host="0.0.0.0") 上边的代码中,import pymysql \ pymysql.install_as_MySQLdb()可以省略,简写在config中 简写 2. 定义类 2.1 作用 通过编写模型类的方式,让程序自动生成数据表模型类也称为实体类 2.2 语法 # 代码中大写单词均为自定义 class MODELNAME(db.Model): __tablename__ = "TABLENAME" COLUMN = db.Column(db.TYPE, OPPTIONS) """ 1. MODELNAME 定义模型类名称,参考表名 2. TABLENAME 指定要映射到的表名,如果不存在的话,则创建表 3. COLUMN 属性名,映射到数据表中就是列名 4. TYPE 映射到列的数据类型 5. OPPTIONS 列选项 """ db.TYPE列类型 数据类型对应表 OPPTIONS列选项 opptions class Usres(db.Model): __tablename__ = "users" id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(20), nullable=False, unique=True) age = db.Column(db.Integer) email = db.Column(db.String(120), unique=True) def __init__(self, username, age, email): self.username = username self.age = age self.email - email def __repr__(self): return "<用户名:%r 年龄:%r 邮箱:%r>"%(self.username, self.age, self.email) #将创建好的实体类映射回数据库 db.create_all() ## 创建Student实体类,表名student """ 1. id 主键 自增 2. sname 姓名 长度30 不为空 3. sage 年龄 整数 4. isActive 启用状态 bool类型 默认为True """ ## 创建Teacher类,表名teacher """ 1. id 主键 自增 2. tname 姓名 长度30 不为空 3. tage 年龄 整数 """ ## 创建Course类,表名course """ 1. id 主键 自增 2. cname 课程名称 长度30 """ class Student(db.Model): __tablename__ = "student" id = db.Column(db.Integer, primary_key=True, autoincrement=True) sname = db.Column(db.String(30), unique=True) sage = db.Column(db.Integer) isActive = db.Column(db.Boolean, default="True") class Teacher(db.Model): __tablename__ = "teacher" id = db.Column(db.Integer, primary_key=True, autoincrement=True) tname = db.Column(db.String(30), unique=True) tage = db.Column(db.Integer) class Course(db.Model): __tablename__ = "course" id = db.Column(db.Integer, primary_key=True, autoincrement=True) cname = db.Column(db.String(30), unique=True) 3. 数据迁移 3.1 定义 将实体类的改动再次映射回数据库 3.2 依赖于第三方库 Flask-script 包:flask_script 类:Manager 作用:对项目进行管理(启动项目、增加管理指令) flask-migrate 包:flask_migrate 类:Migrate(协调app和db之间的关系)、MigrateCommand(在终端中提供实体类迁移的指令) 3.3 使用 修改app.config #指定数据库不追踪 app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False # 指定启动的模式为调试模式 app.config["DEBUG"] = True 创建管理对象:manage = Manager(app) 启动:manager.run()(但是项目的启动需在终端中执行python demo.py runserver) 在使用了manger启动项目的时候,如需开启相关服务,如debug。。。 在终端启动的时候加参数python demo,py runserver --host 0.0.0.0 配置app.config:app.config["DEBUG"] = True 导入from flask_migrate import Migrate, MigrateCommand 在实体类之前创建migrate = Migrate(app, db) 增加一个子命令manage.add_command("db", MigrateCommand) 3.4 迁移 python run.py db init 作用:执行项目和数据库的初始化操作 特点:一个项目中只执行一次即可 python run.py db migrate 作用:将编辑好的实体类生成一个中间文件并保存 特点:只要检测到实体类有更改,就会生成中间文件 python run.py db upgrade 作用:将中间文件映射到数据库 from flask import Flask, request, render_template, url_for from flask_sqlalchemy import SQLAlchemy from flask_script import Manager from flask_migrate import Migrate, MigrateCommand app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:Asd.1234@127.0.0.1:3306/run02" app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False app.config["DEBUG"] = True app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True db = SQLAlchemy(app) manage = Manager(app) migrate = Migrate(app, db) manage.add_command("db", MigrateCommand) 六、模型 1. 增 创建实体类对象,并为对象的属性赋值 user