浅谈 Flask 框架
一、框架对比
Django —— 教科书式框架
优势:组件全,功能全,教科书
劣势:占用资源,创建复杂度高
Flask —— 以简单为基准开发,一切从简,能省则省
优势:轻,块
劣势:先天不足,第三方组件稳定性较差
Django | Flask |
---|---|
Admin —— Model | 原生无 |
Model | 原生无 |
Form | 原生无 |
Session | 有 —— 颠覆认知操作 |
二、Flask入门
下载安装
下载:pip install Flask
注意:不要使用工具中的插件创建 Flask 项目
三行代码启动Flask项目
from flask import Flask
app = Flask(__name__)
app.run()
三、Flask的请求和响应
3.1 Flask中的响应Response
与django对比
Django Flask 返回 HttpResponse("hello") "hello" 字符串 render(request,"html",{"k":v}) render_template("html",k=v) html页面 redirect("/") redirect("/") 重定向 JsonResponse({"k":v}) jsonify({"k":v}) 标准的json字符串 以上是web框架的Response三剑客
返回字符串 —— string
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "hello World I am Flask"
app.run()返回html页面 —— string
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/index")
def index():
return render_template("index.html")
app.run()返回重定向 —— string
from flask import Flask, redirect
app = Flask(__name__)
@app.route("/login")
def login():
return redirect("/index")
app.run()返回文件内容 —— Response instance
send_file():读取并返回文件内容,自动识别文件类型,Content-type中添加类型,即,Content-type:文本类型
浏览器特性:
可识别的Content-type,会自动渲染
不可识别的Content-type,会自动下载
from flask import Flask, send_file
app = Flask(__name__)
@app.route("/get_file")
def get_file():
# 返回文件内容,自动识别文件类型,Content-type中添加文件类型,Content-type:文件类型
return send_file("2.exe")
app.run()返回标准格式的json字符串 —— string
jsonify():返回标准格式的json字符串,本质:先序列化json的字典,Content-type中加入Application/json,Flask1.1.1 直接返回字典格式,相当于自动执行jsonify
from flask import Flask, send_file
app = Flask(__name__)
@app.route("/get_json")
def get_json():
d = {"k":"v"}
# 返回标准Json格式字符串 API接口
return jsonify(d)
app.run()
3.2 Flask中的请求Request
与django对比
Django Flask Flask中的含义 request.method request.method 获取请求方式 request.GET request.args 获取URL中的数据 request.POST request.form 获取FormData中的数据 ,也就是所谓的Form标签 request.FILES request.files 获取request中的文件,返回FileStorage中,存在save(保存文件)和filename(原始文件名) request.json 请求中Content-Type:application/json,请求体中的数据被序列化到 request.json中,以字典的形式存放 request.data 请求中Content-Type中不包含Form或FormData,保留请求体中的原始数据,bytes类型 request.path_info request.path 请求路径 路由地址 request.get_full_patch() request.url 访问请求的完整路径包括 url参数 request.get_host() request.host 主机位 127.0.0.1:5000 request.COOKTES request.cookies 字典获取浏览器请求时带上的Cookie 注意:request.values,获取url和FormData中的数据,敏感地带(url和FormData中存在相同的key时会出错)
import os
from flask import Flask, request, render_template
# request 请求上下文管理
app = Flask(__name__)
@app.route("/login",methods=["GET","POST"])
def login():
# print(request.args.to_dict())
# print(request.host)
# print(request.path)
# print(request.url)
# print(request.cookies)
# 优先判断 请求方式
# 如果是 GET 请求 返回登录页面
if request.method == "GET":
return render_template("login.html")
# 如果是 POST 请求 获取用户名密码 校验
else: # 405 请求方式不被允许
my_file = request.files.get("my_file")
filename = my_file.filename # 获取原始文件名
file_path = os.path.join("avatar",filename)
my_file.save(file_path)
print(request.form.to_dict()) # form - FormData
if request.form.get("username") == "YWB":
return "Login OK!"
return "Login 不OK!"
if __name__ == '__main__':
app.run()
示例
四、 Jinja2:template语言
{{ }} 引用或执行
{% %} 逻辑引用
STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'}
STUDENT_LIST = [
{'name': 'Old', 'age': 38, 'gender': '中'},
{'name': 'Boy', 'age': 73, 'gender': '男'},
{'name': 'EDU', 'age': 84, 'gender': '女'}
]
STUDENT_DICT = {
1: {'name': 'Old', 'age': 38, 'gender': '中'},
2: {'name': 'Boy', 'age': 73, 'gender': '男'},
3: {'name': 'EDU', 'age': 84, 'gender': '女'},
}
from flask import Flask, render_template, Markup
app = Flask(__name__)
@app.template_global()
def ab(a,b):
return a+b
@app.route("/")
def home():
return render_template("stu.html",stu=STUDENT,stu_l = STUDENT_LIST,stu_d = STUDENT_DICT)
@app.template_global()
def my_input(na,ty):
s = f"<input type='{ty}' value='{na}'>"
return Markup(s)
if __name__ == '__main__':
app.run()<p>{{ ab(50,60) }}</p> {{ stu }}
<table border="1px">
<tr>
<td>name</td>
<td>age</td>
<td>gender</td>
</tr>
<tr>
<td>{{ stu.name }}</td>
<td>{{ stu["age"] }}</td>
<td>{{ stu.get("gender") }}</td>
</tr>
</table> {{ stu_l }}
<table border="1px">
<tr>
<td>name</td>
<td>age</td>
<td>gender</td>
</tr>
{% for student in stu_l %}
<tr>
<td>{{ student.name }}</td>
<td>{{ student["age"] }}</td>
<td>
{% if student.get("gender") != "男" and student.get("gender") != "女" %}
女
{% else %}
{{ student.get("gender") }}
{% endif %}
</td>
</tr>
{% endfor %}
</table> {{ stu_d }}
<table border="1px">
<tr>
<td>id</td>
<td>name</td>
<td>age</td>
<td>gender</td>
</tr>
{% for skey,svalue in stu_d.items() %}
<tr>
<td>{{ skey }}</td>
<td>{{ svalue.get("name") }}</td>
<td>{{ svalue.get("age") }}</td>
<td>
11111
</td>
</tr>
{% endfor %}
</table>stu.html
五、Flask的知识点
5.1 Flask中的session
基于请求上下文管理机制
STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'}
STUDENT_LIST = [
{'name': 'Old', 'age': 38, 'gender': '中'},
{'name': 'Boy', 'age': 73, 'gender': '男'},
{'name': 'EDU', 'age': 84, 'gender': '女'}
]
STUDENT_DICT = {
1: {'name': 'Old', 'age': 38, 'gender': '中'},
2: {'name': 'Boy', 'age': 73, 'gender': '男'},
3: {'name': 'EDU', 'age': 84, 'gender': '女'},
}
from flask import Flask, render_template, request, session, redirect
app = Flask(__name__)
# app.config["DEBUG"] = True
app.debug = True
app.secret_key = "!@#$%^(*&^%$#@#$%&*(^$WQ*(^EWET*^EWEU" def war(func): # func = home
def inner(*args,**kwargs):
# 校验session
if session.get("user"):
ret = func(*args,**kwargs) # func = home
return ret
else:
return redirect("/login")
return inner @app.route("/")
@war # war(home) -> inner == == home
# 先要经过一次校验 才能执行或不执行视图函数
def home():
# 校验用户登录 session
#如果session。get(“user”) 存在
# 如果不存在 返回Login
return render_template("stu.html",stu=STUDENT,stu_l = STUDENT_LIST,stu_d = STUDENT_DICT) @app.route("/a")
def homea():
# 校验用户登录状态?
# 校验session中有没有 user Key
if session.get("user"):
inp = Markup("<input type='submit' value='后端给返回的按钮'>")
return render_template("my_a.html", btn=inp)
# 校验失败
# 跳转login
else:
return redirect("/login") @app.route("/login",methods=["GET","POST"])
def login():
# 当请求方式为 GET 的时候
if request.method == "GET":
# eyJ1c2VyIjoiYWxleGFuZGVyLmRzYi5saSJ9.XUfYMw.o8oZX2GMC-kjZPWBkyRuUeSMp4M
# 交由客户端保管机制
# {"user":"alexander.dsb.li"}
# Flask理念 - 一切从简 为服务器减轻压力
return render_template("login.html")
else:
user_info = request.form.to_dict()
session["user"] = user_info.get("username")
print(session.get("user"))
return "login OK!" if __name__ == '__main__':
app.run("0.0.0.0",9527)
5.2 Flask中的路由
@app.route()
参数:
rule:路由地址,例,"/login"
methods:允许进入视图函数的请求方式
endpoint:mapping ,路由地址和endpoint之间的mapping,路由地址和视图函数之间还有一个mapping,注意,endpoint在同一个app中不能出现重复,默认值是视图函数名
defaults:默认路由参数
strict_slashes:是否严格遵循路由匹配规则
redirect_to:永久重定向 ,308和301
from flask import Flask,request,url_for
# url_for用于对endpoint设置的名称的反向获取url
app = Flask(__name__) @app.route("/a",methods=["GET","PoSt","options","abc"],endpoint="end_homea" ,defaults={"count":20},strict_slashes=True,redirect_to="/")
def homea(count):
# print(url_for("end_homea"))
# 如果在蓝图里面,要使用url_for("蓝图标识".endpoint)
# 如文件名为app01,则url_for("app01.end_homea")
count = request.args.get("count",count)
return f"200OK!{count}"
示例
动态参数路由
可以分页,获取文件,解决分类,解决正则路由问题
from flask import Flask,request,url_for
# url_for用于对endpoint设置的名称的反向获取url
app = Flask(__name__) @app.route("/get_img/<filename>")
def get_img(filename):
filepath = os.path.join("img", filename)
return send_file(filepath) # 访问地址 : http://127.0.0.1:5000/info/1
@app.route("/info/<int:nid>", methods=["GET", "POST"], endpoint="r_info")
def student_info(nid):
print(url_for("r_info",nid=2)) # /info/2,反向url时也要加上参数
return f"Hello Old boy {nid}" # Python3.6的新特性 f"{变量名}"
5.3 Flask初始化配置
常用配置:
template_folder:模板文件存放路径
static_folder:静态文件存放目录,默认值是static
static_url_path:静态文件访问路径,默认值是/ + static_folder
from flask import Flask
app = Flask(__name__,template_folder="templatess",
static_folder="static",static_url_path="/futeng")
# static == 你的家
# /static == 回家路
# /futeng == 富腾路
示例
5.4 Flask实例配置
Flask实例配置,即app的配置,可以在app.default_config中查看
# 在setting.py中,写配置对应的类
import hashlib,time
class DebugConfig(object):
DEBUG = True
SECRET_KEY = "#$%^&*($#$%^&*%$#$%^&*^%$#$%"
PERMANENT_SESSION_LIFETIME = 3600
SESSION_COOKIE_NAME = "I am Not Session" class TestConfig(object):
TESTING = True
SECRET_KEY = hashlib.md5(f"{time.time()}#$%^&*($#$%^&*%$#$%^&*^%$#$%{time.time()}".encode("utf8")).hexdigest()
PERMANENT_SESSION_LIFETIME = 360000
SESSION_COOKIE_NAME = "#$%^&*($#$%^&*%$#$%^&*^%$#$%" # 在可执行文件中,调用
from flask import Flask
from setting import DebugConfig,TestConfig app = Flask(__name__)
app.config.from_object(DebugConfig)
# 或 app.config.from_object(TestConfig)
5.5 Flask的蓝图
- 蓝图:Blueprint,不能被run的Flask实例 不存在Config
# 在可执行文件中,调用
from flask import Flask
from users import bp
from car_users import car_bp app = Flask(__name__)
app.register_blueprint(bp)
app.register_blueprint(car_bp)from flask import Blueprint
bp = Blueprint("app01",__name__) @bp.route("/add_user")
def add_user():
return "添加用户" @bp.route("/find_user")
def find_user():
return "查看用户" @bp.route("/drop_user")
def drop_user():
return "删除用户" @bp.route("/up_user")
def up_user():
return "修改用户"users.py
from flask import Blueprint
car_bp = Blueprint("app02",__name__,url_prefix="/car")
# 参数url_prefix是为了区分users.py和car_users.py中的相同路由
# 使用url_prefix后,访问时,要在原来路由前加上url_prefix设置的路径 @car_bp.route("/add_user")
def add_user():
return "car添加用户" @car_bp.route("/find_user")
def find_user():
return "car查看用户" @car_bp.route("/drop_user")
def drop_user():
return "car删除用户" @car_bp.route("/up_user")
def up_user():
print("I am vf")
return "car修改用户"car_users.py
5.6 Flask特殊装饰器
@app.before_request:在请求进入视图函数之前 做出处理
@app.after_request:在响应返回客户端之前,结束视图函数之后
@app.before_request
def be1():
print("I am Be1")
# return "第一个请求你就过不去" # 5种 @app.before_request
def be2():
print("I am Be2")
# return "第二个请求过不去了" # 5种 @app.after_request
def af1(res):
print("I am af1")
return res @app.after_request
def af2(res):
print("I am af2")
return res
示例
be+af 请求生命周期:
正常:be1 -> be2 -> vf -> af2 -> af1
异常:be1 -> af2 -> af1
注意:只要有响应返回 , af全部执行
@app.errorhandler:重定义错误页面
@app.errorhandler(404) # 只能是 4xx,5xx
def error404(error_message):
print(error_message)
# return redirect("https://www.autohome.com.cn/111232130/#pvareaid=33112794r5454") # 5种类型
示例
5.7 Flask的CBV
CBV:继承 MethodView 让当前的 class 可以成为视图类
from flask import Flask
app = Flask(__name__) class Login(views.MethodView):
def get(self,*args,**kwargs):
return "I am Get" def post(self,*args,**kwargs):
pass app.add_url_rule("/login",
endpoint="my_login", # 可以不设置endpoint
view_func=Login.as_view(name="loginlogin") # view_func.__name__="loginlogin"
)
六、Flask组件:Flask-Session
下载:pip install Flask-Session
使用:
from flask import Flask
from flask_session import Session
from redis import Redis app = Flask(__name__)
app.config["SESSION_TYPE"] = "redis"
app.config["SESSION_REDIS"] = Redis(host="192.168.12.87",port=6379,db=10)
# app.session_interface # Flask 利用 session_interface 选择 Session 的存放位置 和 存放机制
# app.default_config Session(app)
七、Flask总结
下载:pip install Flask
启动:
from flask import Flask
app = Flask(__name__)
app.run("0.0.0.0",9527) # 监听地址 监听端口response
# Flask 三剑客
return "" # 返回字符串 HTTPResponse
return render_template("index.html") # 返回模板 依赖MarkupSafe 默认存放路径:templates
return redirect("/login") # 响应头中加入 - location:重定向
# Flask 特殊Response
return send_file(文件名称或文件路径+文件名称) # 打开并返回文件内容 自动识别文件类型 响应头 Content-Type:文件类型
return jsonify({k:v}) # 返回标准格式的json字符串 响应头中 Content-Type:application/json
# Flask 1.1.1中直接返回dict 本质上是在运行jsonifyrequest
from flask import request
request.form # 获取FormData中的数据 to_dict() 类似字典类型 .get() ["key"] KeyError
request.args # 获取URL中的数据 to_dict() 类似字典类型 .get() ["key"] KeyError
request.json # 请求头中 Content-Type:application/json 存放字典
request.data # 请求头中 Content-Type没有Form FormData 存放bytes类型 request.method # 请求方式
request.cookies # 浏览器的cookie键值对
request.headers # 请求头
request.path # 路由地址 请求地址
request.url # 请求全部地址
request.host # 主机位session 交由客户端保管机制 保管一串儿加密字符串
from flask import session
app.config["SECRET_KEY"] = "@#$%^&*(()*&^%$#*&^&%^&*)"
session["key"] = "value"路由配置 route
@app.route(
rule, # 路由地址
endpoint, # mapping 名称对应路由地址 url_for 反向推算路由地址 url_for(endpoint)
methods, # 允许进入视图函数的 请求方式
redirect_to, # 永久重定向 301 308
strict_slashes, # 是否严格遵循路由匹配规则
defalut, # 默认参数
) @app.add_url_rule(
rule,
view_func, # 视图函数
) # 动态参数路由
@app.route("/get_file/<filename>")
def get_file(filename):
pass初始化配置
Flask(__name__,
template_folder, # 模板存放文件
static_folder, # 静态文件存放目录
static_url_path, # 静态文件访问路径
)config
class DebugConfig(object):
DEBUG = True
... app.config.from_object(DebugConfig)蓝图 Blueprint 当成不能被 run 的 Flask 实例
from flask import Blueprint
bp = Blueprint("bp",__name__,
url_perfix, # url前缀
)
@bp.route("/mybp",endpont="")
@bp.add_url_rule
@bp.before_request
@bp.after_request
@bp.errorhandler(http错误码) url_for("蓝图标识".endpoint)
url_for("bp.666") app.register_blueprint(bp)特殊装饰器
@app.before_request # 在请求进入视图函数之前,做出处理
@app.after_request # 在结束视图函数之后,响应客户端之前
@app.errorhandler(http错误码) # 重定向错误信息
def error404(errorMessage):
passCBV
from flask import views
class Login(views.MethodView):
def get(self,*args,**kwargs):
pass
app.add_url_rule("/login",endpoint=None,view_func=Login.as_view(name="loginlogin"))
# name是当前视图函数名,必须唯一,因为他是endpoint
浅谈 Flask 框架的更多相关文章
- 浅谈flask源码之请求过程
更新时间:2018年07月26日 09:51:36 作者:Dear. 我要评论 这篇文章主要介绍了浅谈flask源码之请求过程,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随 ...
- 手撸ORM浅谈ORM框架之基础篇
好奇害死猫 一直觉得ORM框架好用.功能强大集众多优点于一身,当然ORM并非完美无缺,任何事物优缺点并存!我曾一度认为以为使用了ORM框架根本不需要关注Sql语句如何执行的,更不用关心优化的问题!!! ...
- 手撸ORM浅谈ORM框架之Add篇
快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...
- 手撸ORM浅谈ORM框架之Update篇
快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...
- 手撸ORM浅谈ORM框架之Delete篇
快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...
- 手撸ORM浅谈ORM框架之Query篇
快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...
- 【SSH学习笔记】浅谈SSH框架
说在前面 本学期我们有一门课叫做Java EE,由陈老师所授,主要讲的就是Java EE 中的SSH框架. 由于陈老师授课风格以及自己的原因导致学了整整一学期不知道在讲什么,所以才有了自己重新学习总结 ...
- 浅谈angular框架
最近新接触了一个js框架angular,这个框架有着诸多特性,最为核心的是:MVVM.模块化.自动化双向数据绑定.语义化标签.依赖注入,以上这些全部都是属于angular特性,虽然说它的功能十分的强大 ...
- 浅谈 Web框架
一.Web框架本质 所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端 二.Web框架功能 socket收发消息 —— wsgiref(测试).uwsgi(线上 ...
随机推荐
- 使用Fiddler进行HTTP流量分析
- 安装 Fiddler是一款免费软件,可以到其官网下载,地址是https://www.telerik.com/fiddler,也可以从我的网盘中下载,发送"fiddler"获取下 ...
- NumPy实现数组的拼接和分裂
一.数组的拼接 import numpy as np x=np.array([,,]) x2=np.array([,,])np.concatenate([x,x2]) 输出:array([1, 2, ...
- Python的日志功能
python自带的logging是日志处理模块,可以记录日志,并输出到控制台和文件等.日志分5个级别:DEBUG:调试信息,权重10INFO:一般信息,权重20WARNING:警告信息,权重30ERR ...
- [MySQL] 解决Error 1698: Access denied for user 'root'@'localhost'
当程序中使用root账号连接mysql时报以下错误,但是使用命令行是可以正常连接的,那么就查询下mysql数据库的user表,查看下当前用户的密码加密方式,看看是不是unix_socketMariaD ...
- AtCoder - 2565(思维+暴力)
题意 https://vjudge.net/problem/AtCoder-2565 将一个H*W的矩形切成三份,每一次只能水平或者垂直切,问最大块的面积-最小快的面积 的最小值是多少. 思路 先枚举 ...
- C学习笔记(6)--- 共用体,位域深入
1.共用体(Union): 共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型.您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值.共用体提供了一种使用相同的内存位置 ...
- Linux文件基本命令
Linux文件基本命令学习 操作技巧: 输入文件/目录/命令的前几个字母之后,按下tab键,则自动补全 按上/下,回滚曾经用过的命令 不想执行命令使用:crtl + c 基础命令: ls(查看) 基础 ...
- vue 组件之纯表格渲染--没有事件交互
组件 名称小写==> 用-链接 02===> 属性==> empty-text="暂无数据" 当表格中没有数据 就会显示 暂无数据 <el-table-co ...
- 27.Java基础_多态
父类对象引用子类对象: Animal a=new Cat(); 多态中的转型 public class Animal { public void eat(){ System.out.println(& ...
- c# WF 第1节 创建winform程序
本节内容: 1:vs的RAD 2:WinForm的创建简介 3:创建窗口与控制台程序文件的对比 4:窗口文件内容 5:winform怎么运行 6:winform的实质 1:vs的RAD 2:WinFo ...