文章目录
- 一、Flask介绍
- 二、Flask快速使用
- 三、Flask展示用户信息案例
- 四、Flask配置文件
- 五、路由系统
- 1)路由系统
- 2)路由本质
- 3)Add_url_rule的参数
- 六、Flask的CBV
- 1)CBV的写法
- 2)CBV添加装饰器
- 3)as_view的执行流程
- 4)Login.as_view(name='index') name到底有什么用?
- 5)CBV中得methods作用
- 七、模板语法
一、Flask介绍
Flask是一个使用 Python 编写的轻量级 Web 应用框架,其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助Jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。
“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。
默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。
二、Flask快速使用
安装Flask
pip install Flask
快速使用
from flask import Flask
app = Flask(__name__) # 类实例得到一个对象
@app.route('/') # 注册路由
def hello_world(): # put application's code here
return 'Hello World!'
if __name__ == '__main__':
app.run() # 默认是host='127.0.0.1', port=5000端口
'''
这个时候访问5000端口跟路径就能看到 Hellow World了
'''
三、Flask展示用户信息案例
app.py
from flask import Flask, request, render_template, redirect, session
app = Flask(__name__)
app.debug = True
# print(app.config) # 拿到当前app配置
app.secret_key = 'asdadadadLIkeasda1*asd12(01231' # 如果需要使用到session需要配置密钥否则报错
USERS = {
1: {'name': 'Like', 'age': 21, 'gender': '男'},
2: {'name': 'Lisa', 'age': 22, 'gender': '女'},
3: {'name': 'Alice', 'age': 23, 'gender': '女'},
}
@app.route('/login', methods=['GET', 'POST'])
def login(): # put application's code here
if request.method == 'GET':
return render_template('login.html') # 模版都需要写在templates里面 可以通过settings修改名称
else:
username = request.form.get('username') # Flask取数据从form里面获取
password = request.form.get('password')
if username == 'Like' and password == '123':
session['is_login'] = True
return redirect('/index')
else:
return render_template('login.html', errors='用户名或密码错误')
@app.route('/index', methods=['GET'])
def index():
if session.get('is_login'):
return render_template('index.html', **{'users': USERS})
else:
return redirect('/login')
@app.route('/detail/<int:id>')
def detail(id):
if session.get('is_login'):
user = USERS.get(id)
return render_template('detail.html', **{'user': user})
else:
return redirect('/login')
if __name__ == '__main__':
app.run()
"""
总结:
1.注册路由:@app.route(" /detail/<int:id>" ,methods=['GET']) methods:允许的请求方式
2.新手四件套:
-返回模板:return render_template (' detail.html” , **{'user':user}) # Context跟Django不一样
-返回重定向:return redirect('/Login')
-返回字符串:return '字符串'
-返回json格式:return jsonify
3. 使用cookie---就是session,全局的,导入使用即可,必须要指定秘钥
-放值:session[key] = value
-取值:session.get('key')
4.转换器:@app.route('/detail/<int:id>'), 配合视图函数写法
def detail(id)
5.前端Post请求 提交数据
request.form
6.模版语法:兼容Django的Dtl语法, 它可以使用 V. V[''] V.get() 取值
"""
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>
<p>用户名: <input type="submit" value="登录"> <span>{{ errors }}</span></p>
</form>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
{% for k,v in users.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.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户名称:{{ user.name }}</h1> {# 支持Django中的Dtl语法 #}
<h1>用户年龄:{{ user.age }}</h1>
<h1>用户性别:{{ user.gender }}</h1>
</body>
</html>
四、Flask配置文件
Flask中的配置文件是一个flask.config.config对象(继承字典)如果不配置的话是有默认配置的
{
'DEBUG': get_debug_flag(default=False),
'TESTING': False,
'PROPAGATE_EXCEPTIONS': None,
'PRESERVE_CONTEXT_ON_EXCEPTION': None,
'SECRET_KEY': None,
'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
'USE_X_SENDFILE': False,
'LOGGER_NAME': None,
'LOGGER_HANDLER_POLICY': 'always',
'SERVER_NAME': None,
'APPLICATION_ROOT': None,
'SESSION_COOKIE_NAME': 'session',
'SESSION_COOKIE_DOMAIN': None,
'SESSION_COOKIE_PATH': None,
'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False,
'SESSION_REFRESH_EACH_REQUEST': True,
'MAX_CONTENT_LENGTH': None,
'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12),
'TRAP_BAD_REQUEST_ERRORS': False,
'TRAP_HTTP_EXCEPTIONS': False,
'EXPLAIN_TEMPLATE_LOADING': False,
'PREFERRED_URL_SCHEME': 'http',
'JSON_AS_ASCII': True,
'JSON_SORT_KEYS': True,
'JSONIFY_PRETTYPRINT_REGULAR': True,
'JSONIFY_MIMETYPE': 'application/json',
'TEMPLATES_AUTO_RELOAD': None,
}
修改配置文件
app.config['DEBUG'] = True # 由于Config对象本质上是字典,所以还可以使用app.config.update(...)
app.config.from_pyfile('python文件名称') # 使用本地配置文件
app.config.from_envvar('环境变量名称') # 使用环境变量里面的信息
app.config.from_json('json文件名称') # 必须为Json格式 因为内部会执行json.loads
app.config.from_mapping({'DEBUG': True}) # 字典格式
app.config.from_object('object / path') # python类或类的路径
五、路由系统
1)路由系统
路由的典型写法
@app.route('/detail/<int:id>', methods=['GET', 'POST'], endpoint='detail') # int转换器
"""
methods: 列表规定了请求方式 如果列表中没有请求方式不被允许
endpoint: 路由别名 如果不写会被装饰的函数名作为别名
"""
路由中的默认转换器
DEFAULT_CONVERTERS = {
'default': UnicodeConverter, # 默认
'string': UnicodeConverter, # 字符串
'any': AnyConverter, # 任何类型
'path': PathConverter, # 路径
'int': IntegerConverter, # 数字
'float': FloatConverter, # 小数
'uuid': UUIDConverter, # asdad-asdda-asdaa
}
2)路由本质
1. decorator = app.route('/',methods=['GET','POST'],endpoint='n1') # 如果没有传endpoint,这个地方就是None
def route(self, rule, **options):
# app对象 # rule= / # options = {methods=['GET','POST'], endpoint='n1'}
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
# self是Flask的对象 app:rule路由 endpoint:别名,是None 其他的打散了传入了(methods..)
return f
return decorator
2. @decorator
decorator(index)
# 加了装饰器最终,返回的还是index,只不过执行了 self.add_url_rule(rule, endpoint, f, **options)
"""
Flask类中的add_url_rule方法最终意思:
rule就是装饰器传入的路径与路由
endpoint别名
view_func视图函数不加括号
最终结论“现在不需要使用装饰器来注册路由”
app.add_url_rule('/home', view_func=home, endpoint='home')
...
(最终的结果就像Django中的SimpleRouter自动生成路由 可以写多个)
"""
3)Add_url_rule的参数
@app.route和app.add_url_rule参数:
rule == url
view_func == 视图函数名称
defaluts == None 默认值 需要穿值就是 defaluts = {'K': 'v'}
endpoint == None 名称 用于反向生成url
methods = None 允许请求的方式
strict_slashes = None 对url最后的/符号是否严格要求
# @app.route('/index', strict_slashes=False) 如果是True的话那就需要严格添加/否则匹配失败
redirect_to = None 重定向到指定地址
# @app.route('/index/<int:id>', redirect_to='/home/<id>') 当访问起那么这个路径直接跳转到后面这个路径
六、Flask的CBV
1)CBV的写法
from flask import Flask
from flask.views import MethodView
app = Flask(__name__)
# @app.route('/test', methods=['GET', 'POST'])
class Test(MethodView):
def get(self):
return '我是Get请求'
def post(self):
return '我是Post请求'
app.add_url_rule('/test', view_func=Test.as_view(name='test'))
# app.add_url_rule('/login', view_func=Login.as_view(name='index'))
if __name__ == '__main__':
app.run()
2)CBV添加装饰器
class Test(MethodView):
decorators = ['login', 'auth'] # 在类属性中添加decorators属性列表 是按照列表顺序依次给每个方法添加装饰器
def get(self):
return '我是Get请求'
'''
首先会想我们装饰器的原理
@auth
def view(): 本质就是 view = auth(view) 当作参数传入返回函数
看完源码我们就知道了 是通过for循环的给视图类添加装饰器
'''
3)as_view的执行流程
把源码精简一下
def as_view(cls, name, *class_args, **class_kwargs):
def view(**kwargs):
return self.dispatch_request(**kwargs)
return view
def dispatch_request(self, **kwargs):
meth = getattr(self, request.method.lower(), None)
return meth(**kwargs)
请求来了,路由匹配成功,会执行as_view内的view() 也执行了类中的self.dispatch_request....这个就跟我们Django中的CBV一样了
然后看到self.dispatch_request中方法 ,在当前视图类中反射,请求方式的小写字符串(get,post),如果我们写了这些方法 就会去执行。
4)Login.as_view(name=‘index’) name到底有什么用?
先研究endpoint有什么用,正常的fbv,如果不写endpoint会以函数名作为别名endpoint如何设置的?
如果endpoint为None,它把函数名作为了endpoint
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func) # view_func.__name__
options["endpoint"] = endpoint # 如果都是endpoint就会冲突
Login.as_view(name='index'),name到底有啥用
app.add_url_rule('/login', view_func=Login.as_view('login'))
没有传endpoint,Login.as_view('login')是view函数的内存地址
endpoint会以函数名作为endpoint的值,现在所有函数都是view,必须传入name,来修改调view函数的名字
如果传了endpoint,别名以endpoint为主,如果不传endpoint,别名以name为主
app.add_url_rule('/login', view_func=Login.as_view(name='login'),endpoint='xxx')
5)CBV中得methods作用
视图类中有个属性就是methods = ['GET', 'POST']
用来控制允许的请求方式 写了什么方法 就允许什么请求 若没有写则不能使用该方法
七、模板语法
渲染变量
<table>
{% for k,v in users.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>
<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>
逻辑判断
<body>
<h1>用户列表</h1>
<table>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
</table>
</body>
比Django中多了可以加括号 执行函数 传参数
from flask import Flask,render_template,Markup,jsonify,make_response
app = Flask(__name__)
def func1(arg):
return Markup("<input type='text' value='%s' />" %(arg,))
@app.route('/')
def index():
return render_template('index.html',ff = func1)
if __name__ == '__main__':
app.run()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ff('六五')}}
{{ff('六五')|safe}}
</body>
</html>