一、flask介绍
Flask是一个基于Python开发并且依赖jinja2
模板(DTL)和Werkzeug
(wsgiref) WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。
wsgiref服务器:
from wsgiref.simple_server import make_server
def mya(environ, start_response):
print(environ)
start_response('200 OK', [('Content-Type', 'text/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__':
myserver = make_server('', 8011, mya)
print('监听8010')
myserver.serve_forever()
二、flask快速使用
安装:pip3 install flask
创建flask项目:可以选择pycharm新建项目,或自己创建目录使用pycharm打开。
flask示例:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'hello flask'
if __name__ == '__main__':
app.run() # 把flask项目跑起来
登录、显示用户信息案例:
from flask import Flask, request, render_template, redirect, session, jsonify
# flask中的请求对象是全局的request
# render_template 就是django的render
app = Flask(__name__)
# 使用session,一定要设置秘钥,等同于django配置文件中的密码
app.secret_key = 'flask^^1612879775@@#$#'
app.debug = True # 启用调试模式,修改了代码不用重启,自动重启
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 login():
if request.method == 'GET':
return render_template('login.html')
else:
# request.form 等同于request.POST
name = request.form.get('user')
password = request.form.get('pwd')
if name == 'lqz' and password == '123':
# 登录成功,重定向到首页
# 把登录信息放到session中
session['name'] = name
return redirect('/')
else:
return jsonify({'code': 101, 'msg': '用户名或密码错误'})
@app.route('/', methods=['GET'])
def index():
if session.get('name'):
return render_template('index.html', user_dict=USERS)
else:
# 没有登录,重定向到登陆页面
return redirect('/login')
# @app.route('/detail/<int:pk>', methods=['GET']) # 路径使用转换器
# def detail(pk):
@app.route('/detail', methods=['GET'], endpoint='detail')
def detail():
print(request.query_string) # b'pk=1&name=lqz&age=19'
pk = int(request.args.get('pk')) # 字符串转int
print(pk)
user_detail = USERS.get(pk)
return render_template('detail.html', info=user_detail)
if __name__ == '__main__':
app.run(port=8080)
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户登录</h1>
<form method="post">
<input type="text" name="user">
<input type="text" name="pwd">
<input type="submit" value="登录">{{error}}
</form>
</body>
</html>
index.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}}">查看详细1</a></td>-->
<td><a href="/detail?pk={{k}}">查看详细1</a></td>
<td><a href="/detail?pk={{k}}&name=lqz&age=19">查看详细2</a></td>
</tr>
{% endfor %}
</table>
</body>
</html>
detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>详细信息 {{info.name}}</h1>
<div>
{{info.text}}
</div>
</body>
</html>
总结:
- 当次请求的对象,request对象是全局的,直接导入使用即可
- 前端post提交的数据,从flask中的:
request.form
中取 - 转换器的使用
在路由中:/detail/<int:pk>
@app.route('/detail/<int:pk>', methods=['GET']) # 路径使用转换器
def detail(pk):
user_detail = USERS.get(pk)
return render_template('detail.html', info=user_detail)
<!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>
不使用转换器,没有传参,在模板中:/detail?pk={{k}}
@app.route('/detail', methods=['GET'], endpoint='detail')
def detail():
pk = int(request.args.get('pk')) # 字符串转int
user_detail = USERS.get(pk)
return render_template('detail.html', info=user_detail)
<!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?pk={{k}}">查看详细1</a></td>
<td><a href="/detail?pk={{k}}&name=lqz&age=19">查看详细2</a></td>
</tr>
{% endfor %}
</table>
</body>
</html>
- 模板语法兼容django的dtl,可以直接使用函数加括号,并且可以传参数
- session也是全局对象,用户登录信息,放到session中
- 新手四件套
'字符串'---->HttpResonse('字符串')
redirect('/')---->redirect('/')
render_template()---->render()
jsonify---->JsonResponse()
- 前端get请求提交的数据,从
request.args
request.query_string
是get请求,后面的内容是bytes
格式@app.route('/detail', methods=['GET'],endpoint='detail')
endpoint
等同于django路由中的name
别名(加多个装饰器,函数名会重复,需要加endpoint)
三、Flask配置文件
常用配置:
from flask import Flask
app = Flask(__name__)
# flask把常用的配置直接提到app对象这一层, 实质上他们在app.config中,当字典用
app.debug=True
app.secret_key='asdfasfasdfas'
app.config['DEBUG']=True
app.config['SECRET_KEY']='asdfasdfasdfasfasfdasfasfsfa'
print(app.config)
如何设置配置文件(重点):
-
1 直接写
app.config['DEBUG']
(一般不用) -
2 放到py文件中(一般不用)
app.config.from_pyfile('settings.py')
- 3 通过环境变量(一般不用)
app.config.from_envvar("环境变量名称")
app.config.from_json("json文件名称")
JSON文件名称,必须是json格式,因为内部会执行json.loads
app.config.from_mapping({'DEBUG': True})
- 4 通过类的方式
app.config.from_object('settings.DevelopmentConfig')
用的多的是通过类的方式配置:
from flask import Flask
app = Flask(__name__)
app.config.from_object('settings.ProductionConfig')
print(app.config)
@app.route('/')
def index():
return 'hello flask'
if __name__ == '__main__':
app.run() # 把flask项目跑起来
项目根目录下新建settings.py文件
# DEBUG=True
# SECRET_KEY='asfase33322'
class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = 'sqlite://:memory:'
# 上线环境用这套
class ProductionConfig(Config):
DATABASE_URI = 'mysql://user@localhost/foo'
# 开发环境用这套
class DevelopmentConfig(Config):
DEBUG = True
# 测试环境用这套
class TestingConfig(Config):
TESTING = True