目录
一 小demo
二 杂乱的小知识
1 不用装饰器绑定路由和函数
2 abort 函数, 立即终止对视图的访问
3 markup 渲染后端html到前端
4. 自定义宏
5 闪现 只有第一次访问才能拿到值
6 reques的参数
7 response的参数
8 上下文
三 路由
1.url_for 反向解析
2 加参数
3 其他的参数
4 子域名
四 flask的返回值
五 中间件和各种装饰器
1)用装饰器自定义局部中间件
2) 自定义全局中间件
3)自带的全局中间件before_request
4) after_request
5)before_first_request
6)errorhander()
7) template_global()
8) template_filter()
六 flask 的CBV
七 url 自定义正则
八 蓝图
九 上下文管理
十 flask 上传文件
十一 jinja模板
十二 flask多APP应用
app.py
from flask import Flask, render_template, request, redirect, session
app = Flask(__name__)
app.secret_key = 'xxx' # 用session必须加
print(app.config)
# app.config['DEBUG'] = True
# 还可以自己写个settings文件,导入配置
# app.config.from_object("settings.Foo")
@app.route('/', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('xx.html')
user = request.form.get('user')
pwd = request.form.get('pwd')
if user == 'xx' and pwd == 'xx':
session['user'] = user
return redirect('/index/')
return render_template('xx.html', error='卧槽')
# render_template('xx.html', **{"error": "xx})
# 在前端直接渲染错误信息 {{ error }}
@app.route('/index/')
def index():
user = session.get('user')
if not user:
return redirect('/login/')
render_template('index.html')
if __name__ == '__main__':
app.run()
# app.run(debug=True)
settings.py
class Foo:
DEBUG = False
TEST = True
app.add_url_rule('/'. 'index', index)
三个参数分别为 路由, 反向名, 函数
abort 函数, 立即终止对视图的访问,返回错误信息
from flask import Flask, abort
@app.route('/')
def get_user(id):
user = load_user(id)
if not user:
abort(404)
return xxxxx
from flask import Flask, makeup
@app.route('/xx')
def xx():
content = {
'txt': makeup("")
}
return render_template('xx.html', **content)
{% macro ccc(name, type="text", value='') %}
自定义宏什么都显示
{% endmacro %}
正式调用宏,显示一个input 框
{{ ccc('n1','', 'xx') }}
一般会把宏写在一个单独的文件里
当宏作为一个单独文件时{% include 'xx' %} 要先引用
相当于用seesion存数据, 只能拿到一次里面的数据, 再拿就拿不到了
from flask import Flask, flash, get_flashed_messages
@app.route('/xxx')
def a():
flash('xx') # 相当于设置个seesion
flash('xx', 'eeror') # 相当于价格分类
......
@app.route('/xx')
def b():
print(get_falshed_messages)
print(get_flashed_messages(category_filter=['error']))
from flask import make_response
@app.route('/')
def index():
response = make_response('xx')
response.set_cookie('answer', '22')
return response
https://blog.csdn.net/DeskyAki/article/details/89648260
endpoint相当于django的name, 就是反向解析的名字,flask不写endpoint反向解析的名字默认就是函数名,
url_for 反向解析额url, _external=True 返回绝对地址
from flask import Flask, url_for
@app.route('/index/', methods=['GET', 'POST'], endpoint='n1')
def index():
print(url_for('n1'))
# 打印结果 /index
# print(url_for('n1', _external=True))
# 返回绝对地址
return "index"
url_for也可以匹配静态文件
@app.route('/index/') # 形如/index/2
@app.route('/index/') # 不写默认时字符串
@app.route('/index/') # 浮点类型
@app.route('/index/') # path
@app.route('/index/', method=["GET", "POST"])
def index(nid):
print(url_for("index", nid=999))
# 生成/index/999
关于path, 匹配/
@app.route('/center/')
访问/center/1/1
匹配到的uid 是1/1
@app.route('/index', strict_slashes=False)
# 不严格要求路由, /index/, /index
@qpp.route('/index', strict_slahes=True)
# 严格要求url
@app.route('/index', redirect_to='xx')
# 重定向, 跳转到指定网址
要修改本地的host文件, 完成DNS解析
app = Flask(import_name = __name__)
app.config['SERVER_NAME'] = 'xxx.com:5000'
@app.route("/", subdomain='admin')
def adnm_index():
return ...
http://admin.xxx.com:5000/
from flask import Flask, jsonify, make_response
obj = make_response("index")
obj.headers['xxxxx'] = '123'
obj.set_cookie('key', 'value') # 加session
return obj
中间件详情请看 https://blog.csdn.net/DeskyAki/article/details/97023979
from functools import wraps
def auth(func):
@wraps(func)
def inner(*args, **kwargs):
if not session.get('user'):
return redirect(url_for('login'))
ret = func(*args, **kwargs)
return ret
return inner
@app.route('/login', methods=["GET", "POST"])
@auth
def login():
写在app.py中
class Middleware(object):
def __init__(self, old):
self.old = old
def __call__(self, *args, **kwargs):
print('请求前的操作')
ret = self.old(*args, **kwargs)
print('请求之后操作')
return ret
if __name__ == '__main__':
app.wsgi_app = Middleware(app.wsgi_app)
app.run()
@app.before_request
def xxx():
if request.path == '/login':
return None # return None 接着执行视图 有返回值就地返回
# 或者 return
if request.form.get('user'):
return None
return redirect('/login')
@app.before_request
def x1():
print('before')
@app.after_request
def x2(response): # 必须有response
print('after')
return response
@app.route('/index/')
def index():
print('index')
return "index"
执行打印结果
before
index
after
只有第一次请求才执行一次
@app.before_first_request
def
自定义404错误页面
@app.errorhander(404)
def not_found(arg):
print(arg) # 错误信息
return 'xx'
@app.template_global()
def sb(a1, a2):
return a1 + a2
全局调用
{{ sb(1, 9) }}
@app.template_filter()
def db(a1, a2, a3):
return a1 + a2 + a3
全局调用
{{ 1|db(2, 3) }}
from flask import Flask, views
app = Flask(__name__)
class UserView(views.MethodView):
def get(self, *args, **kwargs):
return "GET"
app.add_url_rule('/user', None, UserView.as_view('随便起的别名'))
from werkzeug.routing import BaseConverter
from flask import Flask, url_for
app = Flask(__name__)
class RegexConverter(BaseConverter):
# 自定义正则
def __init__(self, map, regex):
super(RegexConverter, self).__init__(map)
self.regex = regex
def to_python(self, value):
# 路由匹配时, 匹配成功后传递给视图函数中参数的值
# 拿到路由匹配到的参数, 并做处理
return int(value)
def to_url(self, value):
val = super().to_url(value)
return val
app.url_map.converters['reg'] = RegexConverter
@app.route('/index/')
def index(nid):
print("ffffffff", url_for('index', nid=999))
return redirect(url_for('index', nid=666))
当我们重定向了,并传递参数的时候,参数会先到to_url,返回的值会去匹配路由上的正则。
如果匹配上了,就把匹配到参数传到 to_python ,这个方法返回的值才会到视图函数中。
如果匹配不上,就会报404错误。
详见 https://blog.csdn.net/DeskyAki/article/details/89341262
详见 https://blog.csdn.net/DeskyAki/article/details/89648260
前端
后台
import os
def upload():
if request.method == "GET":
return render_template('xx')
file_obj = request.fiels.get('code')
print(file_obj.filename) # 打印文件名字
print(file_obj.stream) # 打印文件内容
file_obj.save(file_obj.filename) # 自动保存,文件名是filename的值
或者
# 指定保存到的路径
file_path = os.path.join("files", file_obj.filename)
file_obj.save(file_obj.filename)
app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 7
限制文件大小 1K * 1024 * 7 = 7M
详见 https://blog.csdn.net/DeskyAki/article/details/97120847 这篇博客总结的很全面
from flask import Flask,
from werkzeug.wsgi import DispatcherMiddleware
from werkzeug.serving import run_simple
app1 = Flask("app1")
# app1.config['DB'] = 123
app2 = Flask("app2")
# app2.config['DB'] = 234
@app1.route('/a')
def app1index():
return 'app1'
@app2.route('/b')
def app2index():
return 'app2'
app = DispatcherMiddleware(app1, {
'/app2': app2,
})
if __name__ == '__main__':
run_simple('localhost', 5000, app)
# 访问http://localhost:5000/a
# 访问http://localhost:5000/app2/b
from 前面的文件 import app1, app2
with app1.app_content(): # 进入app01
pass # 创建数据库
with app.app_content(): # 进入app02
pass # 创建数据库