目录
Flask框架
前言:
Flask框架和Django框架的区别:
- Django框架:
- 大而全,内置的app的很多,第三方app也很多
- Flask框架:
- 小而精,没有过多的内置app,只能完成web框架的基本功能,很多功能都需要借助第三方
拓展:
-
python异步框架:
- fastapi:https://fastapi.tiangolo.com/zh/
- sanic
- tornado(目前很少人在使用)
- django:3.x以后版本支持异步
-
同步框架和异步框架的区别
- 同步框架: 一个线程只会处理一个请求
- 异步框架: 一个线程可以处理多个请求
- 异步框架可以显著的提高并发量
一、flask介绍
1、介绍
Flask是一个基于Python开发并且依赖于jinja2模板和Werkzeug WSGI服务的一个微型框架
jinja2:
模板语法,和django的dtl非常像
Werkzeug WSGI:
符合wsgi协议的web服务器,django使用的是wsgiref
2、使用两种协议编写web
使用wsgiref编写web
from wsgiref.simple_server import make_server def mya(environ, start_response): # request就是environ包装后的对象 print(environ) start_response('200 OK', [('Content-Type', 'text/html')]) # 分发路由 # 根据用户访问的路由,打开对应的html文件,读取并返回给用户 if environ.get('PATH_INFO') == '/index': with open('index.html', 'rb') as f: data = f.read() elif environ.get('PATH_INFO') == '/login': with open('login.html', 'rb') as f: data = f.read() else: data = b'<h1>Hello Web!</h1>' return [data] if __name__ == '__main__': # 第一个参数是服务的IP(不写默认为127.0.0.1),第二个是监听的端口,第三个是编写的web函数 my_server = make_server('0.0.0.0', 8008, mya) # 启动服务 my_server.serve_forever()

werkzeug WSGI编写服务:
# pip 安装werkzeug # 导入 from werkzeug.wrappers import Request, Response @Request.application def my_server(request): print(request) return Response('Hello Web!') if __name__ == '__main__': # 导入启动服务的模块 from werkzeug.serving import run_simple run_simple('127.0.0.1', 4000, my_server)

二、flask快速使用
安装:
# 安装flask会一并安装其依赖:jinja2、Werkzeug、MarkupSafe pip install flask # 版本问题: -1.x 没有本质区别 -2.x 没有本质区别,源码上动了,用起来一样
1、快速使用:
# 导入模块 from flask import Flask # 实例化对象,参数内是服务的名字,填入任意都可以 app = Flask(__name__) # 编写函数、注册路由(装饰器方法注册) @app.route('/') def index(): return 'hello web!' @app.route('/home') def home(): return 'hello home!' if __name__ == '__main__': # app.run('127.0.0.1', 5000) # 默认监听本地127.0.0.1的5000端口 app.run()
2、使用flask编写登录小案例
2.1 login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post"> <p>用户名:<input type="text" name="username"></p> <p>密码:<input type="password" name="password"></p> <input type="submit" value="登录"> {{error}} </form> </body> </html>
2.2 home.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>用户列表</h1> <table> {% for k,v in user_dict.items() %} <tr> <td>{{k}}</td> <td>{{v.name}}</td> <td>{{v['name']}}</td> <td>{{v.get('name')}}</td> <td><a href="/detail/{{k}}">查看详细</a></td> </tr> {% endfor %} </table> </body> </html>
2.3 detail.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>名字是:{{user.name}}</p> <p>年龄是:{{user['age']}}</p> <p>性别是:{{user.get('gender')}}</p> <p>{{user.text}}</p> </body> </html>
2.4 py文件
from flask import Flask, request, render_template, session, redirect app = Flask(__name__) # 使用session需要指定key app.secret_key = 'abc123' USERS = { 1: {'name': '张三', 'age': 18, 'gender': '男', 'text': "道路千万条"}, 2: {'name': '李四', 'age': 28, 'gender': '男', 'text': "安全第一条"}, 3: {'name': '王五', 'age': 18, 'gender': '女', 'text': "行车不规范"}, } @app.route('/login', methods=['GET', 'POST']) def index(): # 判断路由的方式 if request.method == 'GET': # 返回登陆页面给用户 return render_template('Login.html') # post请求判断用户名密码 if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') # 校验用户名或密码 if username == 'kangkang' and password == '123': # 校验成功,保存session(导入、全局使用) session['name'] = username # 重定向到home页面(导入redirect) return redirect('/') else: # 用户名或密码错误 return render_template('Login.html', error='用户名或密码错误') # 编写首页 @app.route('/') def home(): # 先校验用户是否登录 if session.get('name'): # 校验登录通过,展示首页 return render_template('Home.html', user_dict=USERS) else: # 没有登陆跳转到登陆页面 return redirect('/login') # 编写用户详情页 @app.route('/detail/<int:pk>') def detail(pk): # 先校验用户是否登录 if session.get('name'): # 校验登录通过,展示详情页面 user_detail = USERS[pk] return render_template('Detail.html', user=user_detail) else: # 没有登陆跳转到登陆页面 return redirect('/login') if __name__ == '__main__': app.run()
三、flask配置文件
1、配置文件的几种方式
flask不同于django可以在settings文件编写配置,flask配置文件的方式有多种,相较于django更加灵活
方式一:直接编写
# 在编写app的我呢见中直接编写配置(用于测试) app.debug=True # 调试模式,提示信息更详细,修改代码不需要重启,自动重启 app.secret_key='dasdfasdfasd' # 秘钥,只能 放debug和secret_key
方式二:使用app.config
# 直接使用flask实例化的对象点出config的方式添加 app.config['DEBUG']=True app.config['SECRET_KEY']='sdfasdfasd' print(app.config)
方式三:使用py文件,然后载入
# 将配置编写在py文件中,然后使用方法导入(不常用) app.config.from_pyfile("settings.py") # 变量必须大写 print(app.config)
方式四:使用类导入
# 同样是创建py文件,区别是写在类中,可以上线时候可以指定使用哪套 app.config.from_object('settings.DevelopmentConfig') app.config.from_object('settings.ProductionConfig') print(app.config)
方式五:其他方式
# 1、通过环境变量导入 app.config.from_envvar("环境变量名称") # 2、通过json文件载入 app.config.from_json("json文件名称") # JSON文件名称,必须是json格式,因为内部会执行json.loads # 3、字典格式、配置中心 app.config.from_mapping({'DEBUG': True})
2、常用的配置字段
-DEBUG # debug模式 -SECRET_KEY # session的key值 (密钥) -SESSION_COOKIE_NAME # 用户浏览器上cokie会变成设置的名字 -PERMANENT_SESSION_LIFETIME # session过期时间 # 内置的配置字段,其他可以写自己的,比如 redis的连接地址,mysql的连接地址
四、路由系统
1、路由的本质
在django中,路由写在urls.py文件下的path列表中
flask是基于装饰器的,大部分都是使用装饰器来做,少量的可以抽取到urls.py中
路由装饰器源码分析:
# 咱们这样写 @app.route('/login') def index(): pass #本质是---》index=app.route('/login')(index) # app.route('/login')的执行结果 decorator 函数 -rule是路径 -其他参数都给了options # 然后 decorator(index)--->在执行 # f是index endpoint = options.pop("endpoint", None) # 目前没有endpoint,是None # 核心,本质--》self就是实例化得到的app对象,flask对象 # app对象中有个方法add_url_rule,这是在添加路由 # 不使用装饰器,自己注册路由 self.add_url_rule(rule, endpoint, f, **options) return f def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: def decorator(f: T_route) -> T_route: endpoint = options.pop("endpoint", None) self.add_url_rule(rule, endpoint, f, **options) return f return decorator # 可以不使用装饰器的方式,注册路由 app.add_url_rule('/', endpoint=None, view_func=home, methods=['GET']) # flask路由的本质是app对象的add_url_rule完成路由的注册
2、add_url_rule参数
# rule URL规则 # view_func 视图函数名称 # defaults = None 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}为函数提供参数 # endpoint = None, 路径的别名,名称,用于反向解析URL,即: url_for('名称') # methods = None, 允许的请求方式,如:["GET", "POST"] #对URL最后的 / 符号是否严格要求 strict_slashes = None ''' @app.route('/index', strict_slashes=False) #访问http://www.xx.com/index/ 或http://www.xx.com/index均可 @app.route('/index', strict_slashes=True) #仅访问http://www.xx.com/index ''' #重定向到指定地址 redirect_to = None, ''' @app.route('/index/<int:nid>', redirect_to='/home/<nid>') ''' # 需要记住的 # rule # view_func # defaults # endpoint # methods
3、转换器
'default': UnicodeConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'path': PathConverter, 'int': IntegerConverter, 'float': FloatConverter, 'uuid': UUIDConverter, # 了解:让路由支持正则(忽略掉)