第十二篇 Flask 基础篇
Flask
-参考文章
文档链接:https://xugaoxiang.com/category/python/flask/
网盘链接:https://pan.baidu.com/s/1vpxFmkH5f2RHwokRJMss1g (300m)
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。
“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。
默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。
1 pip install flask
from werkzeug.wrappers import Request, Response @Request.application def hello(request): return Response('Hello World!') if __name__ == '__main__': from werkzeug.serving import run_simple run_simple('localhost', 4000, hello) werkzeug
一 .基本使用
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run()
使用二:
#!\Users\Local\Programs\Python37
# -*- coding: utf-8 -*-
from flask import Flask,request
import json
app = Flask(__name__)
@app.route('/',methods=["POST","GET"]) #请求的路由与允许的请求方式
def test_api():
if request.method=="POST":
# data =request.form # 1获取表单数据
data =json.loads(request.get_data()) # 2 获取json数据
print(data)
return data
data =request.args #获取get请求参数
# data =request.files #文件上传
# data=request.values # 获取所有参数
print(data)
return "error,请使用POST方式请求!"
if __name__ == '__main__':
app.run(host="0.0.0.0",port=9000,debug=True)
二 .配置文件
from flask import Flask,render_template,redirect app = Flask(__name__) # 配置文件 app.config.from_object("settings.DevelopmentConfig") @app.route('/index',methods=['GET','POST']) def index(): return "index" if __name__ == '__main__': app.run()
setting.py(项目根目录下)
class BaseConfig(object): DEBUG = True SECRET_KEY = "asudflkjdfadjfakdf" class ProductionConfig(BaseConfig): DEBUG = False class DevelopmentConfig(BaseConfig): pass class TestingConfig(BaseConfig): pass
flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为: { 'DEBUG': get_debug_flag(default=False), 是否开启Debug模式 '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 PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...) 方式二: app.config.from_pyfile("python文件名称") 如: settings.py DEBUG = True app.config.from_pyfile("settings.py") app.config.from_envvar("环境变量名称") 环境变量的值为python文件名称名称,内部调用from_pyfile方法 app.config.from_json("json文件名称") JSON文件名称,必须是json格式,因为内部会执行json.loads app.config.from_mapping({'DEBUG':True}) 字典格式 app.config.from_object("python类或类的路径") app.config.from_object('pro_flask.settings.TestingConfig') settings.py 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 PS: 从sys.path中已经存在路径开始写 PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录
三 .路由系统
from flask import Flask,render_template,redirect app = Flask(__name__) """ 1. 执行decorator=app.route('/index',methods=['GET','POST']) 2falsk基础知识与示例. @decorator - decorator(index) """ # 路由方式一(*): @app.route('/index',methods=['GET','POST']) def index(): return "Index" # 路由方式二: def order(): return 'Order' app.add_url_rule('/order',view_func=order) if __name__ == '__main__': app.run()
from flask import Flask,render_template,redirect,url_for app = Flask(__name__) # endpoint 起别名,用于反向生成url @app.route('/index',methods=['GET','POST'],endpoint='n1') def index(): v1 = url_for('n1') v2 = url_for('login') v3 = url_for('logout') print(v1,v2,v3) return "Index" @app.route('/login',methods=['GET','POST']) def login(): return "login" @app.route('/logout',methods=['GET','POST']) def logout(): return "logout" if __name__ == '__main__': app.run()
from flask import Flask,render_template,redirect,url_for app = Flask(__name__) @app.route('/index/<int:nid>',methods=['GET','POST']) def index(nid): print(nid,type(nid)) return "Index2" if __name__ == '__main__': app.run()
from flask import Flask,render_template,redirect,url_for from werkzeug.routing import BaseConverter app = Flask(__name__) class RegexConverter(BaseConverter): """ 自定义URL匹配正则表达式 """ def __init__(self, map, regex): super(RegexConverter, self).__init__(map) self.regex = regex def to_python(self, value): """ 路由匹配时,匹配成功后传递给视图函数中参数的值 :param value: :return: """ return int(value) def to_url(self, value): """ 使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数 :param value: :return: """ val = super(RegexConverter, self).to_url(value) return val app.url_map.converters['xxx'] = RegexConverter @app.route('/index/<xxx("\d+"):nid>',methods=['GET','POST']) def index(nid): print(nid,type(nid)) v = url_for('index',nid=999) # /index/999 print(v) return "Index" if __name__ == '__main__': app.run()
from flask import Flask,render_template,redirect app = Flask(__name__) @app.route('/index',methods=['GET','POST'],redirect_to='/new') def index(): return "老功能" @app.route('/new',methods=['GET','POST']) def new(): return '新功能' if __name__ == '__main__': app.run()
from flask import Flask,render_template,redirect from gevent import pywsgi app = Flask(__name__) app.config['SERVER_NAME'] = 'hw.com:5000' @app.route("/dynamic", subdomain="<username>") def xxxxxxx(username): # 域名为:'www.oldboy.com:5000' print(username) # 获取子域名 输出:www return 'xxxxx' @app.route('/index') def x(): print('x') return 'xxx' if __name__ == '__main__': app.run('127.0.0.1',5000)
from flask import Flask,render_template,redirect app = Flask(__name__) import functools def wapper(func): @functools.wraps(func) # 保留原函数信息 def inner(*args,**kwargs): print('before') return func(*args,**kwargs) return inner @app.route('/xxxx',methods=['GET','POST']) @wapper def index(): return "Index" @app.route('/order',methods=['GET','POST']) @wapper def order(): return "order" if __name__ == '__main__': app.run()
四 .视图(cbv-fbv)
from flask import Flask,render_template,redirect,views app = Flask(__name__) import functools def wapper(func): @functools.wraps(func) def inner(*args,**kwargs): print('before') return func(*args,**kwargs) return inner @app.route('/xxxx',methods=['GET','POST']) @wapper def index(): return "Index" """ class IndexView(views.View): methods = ['GET'] decorators = [wapper, ] def dispatch_request(self): print('Index') return 'Index!' app.add_url_rule('/index', view_func=IndexView.as_view(name='index1')) # name=endpoint """ class IndexView(views.MethodView): methods = ['GET'] #允许请求的方式 decorators = [wapper, ] def get(self): return 'Index.GET' def post(self): return 'Index.POST' app.add_url_rule('/index', view_func=IndexView.as_view(name='index2')) # name=endpoint if __name__ == '__main__': app.run()
五 .请求与相应
from flask import Flask,render_template,redirect,request,jsonify,make_response app = Flask(__name__) @app.route('/index',methods=['GET','POST']) def index(): # 请求相关 # request.method # request.args # request.form # request.cookies # request.headers # request.path # request.files # obj = request.files['the_file_name'] # obj.save('/var/www/uploads/' + secure_filename(obj.filename)) # request.values # request.full_path # request.script_root # request.url # request.base_url # request.url_root # request.host_url # request.host # 响应相关 return "" return json.dumps({}) # return jsonify({}) return render_template('index.html',n1=123) return redirect('/index') # response = make_response(render_template('index.html')) # response = make_response("xxxx") # response.set_cookie('key', 'value') # response.headers['X-Something'] = 'A value' # response.delete_cookie('key') # return response if __name__ == '__main__': app.run()
六 .模板
from flask import Flask,render_template,redirect,request,jsonify,make_response,Markup app = Flask(__name__) @app.template_global() def sbbbbbbb(a1, a2): """ 每个模板中可以调用的函数 :param a1: :param a2: :return: """ return a1 + a2 def gen_input(value): # return "<input value='%s'/>" %value return Markup("<input value='%s'/>" %value) @app.route('/x1',methods=['GET','POST']) def index(): context = { 'k1':123, 'k2': [11,22,33], 'k3':{'name':'oldboy','age':84}, 'k4': lambda x: x+1, 'k5': gen_input, # 当前模板才能调用的函数 } return render_template('index.html',**context) @app.route('/x2',methods=['GET','POST']) def order(): context = { 'k1':123, 'k2': [11,22,33], } return render_template('order.html',**context) if __name__ == '__main__': app.run()
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <div >头部</div> <div> {% block content %} {% endblock %} </div> <div >底部</div> </body> </html>
{% extends 'layout.html'%} {% block content %} <h1>{{k1}}</h1> <h1>{{k2.0}} {{k2[0]}} </h1> <h1>{{k3.name}} {{k3['name']}} {{k3.get('name',888)}}</h1> <h1>{{k4(66)}}</h1> <h1>{{k5(99)}}</h1> <h1>{{sbbbbbbb(1,2)}}</h1> {% endblock%}
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>{{sbbbbbbb(1,2)}}</h1> </body> </html>
七 .session
""" 1. 请求刚刚达到 ctx = RequestContext(...) - request - session=None ctx.push() ctx.session = SecureCookieSessionInterface.open_session 2falsk基础知识与示例. 视图函数 3flsak源码分析上下文管理. 请求结束 SecureCookieSessionInterface.save_session() """ from flask import Flask,session app = Flask(__name__) app.secret_key = 'sadfasdfasdf' @app.route('/x1') def index(): # 去ctx中获取session session['k1'] = 123 session['k2'] = 123 del session['k2'] return "Index" @app.route('/x2') def order(): print(session['k1']) return "Order" if __name__ == '__main__': app.run() # 1. 请求一旦到来显 app.__call__ app.wsgi_app app.open_session
八 .特殊装饰器
from flask import Flask,render_template,redirect app = Flask(__name__) """ before_reuqest = [xxxxxxxxxx1,xxxxxxxxxx2] """ @app.before_request def xxxxxxxxxx1(): print('前1') @app.before_request def xxxxxxxxxx2(): print('前2') """ after_request = [oooooooo1,oooooooo2] [oooooooo2,oooooooo1,] reversed(after_request) """ @app.after_request def oooooooo1(response): print('后1') return response @app.after_request def oooooooo2(response): print('后2') return response @app.route('/x1',methods=['GET','POST']) def x1(): print('视图函数x1') return "视图函数x1" @app.route('/x2',methods=['GET','POST']) def x2(): print('视图函数x2') return "视图函数x2" if __name__ == '__main__': app.__call__ app.run()
from flask import Flask,render_template,redirect app = Flask(__name__) @app.before_request def xxxxxxxxxx1(): print('前1') return "不要再来烦我了" @app.before_request def xxxxxxxxxx2(): print('前2') @app.after_request def oooooooo1(response): print('后1') return response @app.after_request def oooooooo2(response): print('后2') return response @app.route('/x1',methods=['GET','POST']) def x1(): print('视图函数x1') return "视图函数x1" @app.route('/x2',methods=['GET','POST']) def x2(): print('视图函数x2') return "视图函数x2" if __name__ == '__main__': app.__call__ app.run()
from flask import Flask,render_template,redirect,request,session app = Flask(__name__) app.secret_key = 'asdfasdfasdf' @app.before_request def check_login(): if request.path == '/login': return None user = session.get('user_info') if not user: return redirect('/login') @app.route('/login',methods=['GET','POST']) def login(): return "视图函数x1" @app.route('/index',methods=['GET','POST']) def index(): print('视图函数x2') return "视图函数x2" if __name__ == '__main__': app.run()
九 .闪现
from flask import Flask,session,flash,get_flashed_messages app = Flask(__name__) app.secret_key = 'asdfasdfasdf' @app.route('/x1',methods=['GET','POST']) def login(): flash('我要上向龙1',category='x1') flash('我要上向龙2',category='x2') return "视图函数x1" @app.route('/x2',methods=['GET','POST']) def index(): data = get_flashed_messages(category_filter=['x1']) print(data) return "视图函数x2" if __name__ == '__main__': app.run()
十.中间件
from flask import Flask app = Flask(__name__) app.secret_key = 'asdfasdfasdf' Debug =True @app.before_request def xxxxxxxxxx1(): print('前1') @app.route('/x2',methods=['GET','POST']) def index(): return "x2" class Middleware(object): def __init__(self,old_wsgi_app): """ 服务端启动时,自动执行 :param old_wsgi_app: """ self.old_wsgi_app =old_wsgi_app def __call__(self, environ, start_response): """ 每次有用户请求道来时 :param args: :param kwargs: :return: """ print('before') from flask import session,request obj = self.old_wsgi_app(environ, start_response) print('after') return obj if __name__ == '__main__': app.wsgi_app = Middleware(app.wsgi_app) app.run() """ 1.执行app.__call__ 2falsk基础知识与示例.在调用app.wsgi_app方法 """
from types import MethodType,FunctionType class Foo(object): def fetch(self): pass print(isinstance(Foo.fetch,MethodType)) print(isinstance(Foo.fetch,FunctionType)) # True obj = Foo() print(isinstance(obj.fetch,MethodType)) # True print(isinstance(obj.fetch,FunctionType))
十一 .蓝图
蓝图示例 s8pro/s8pro _init_.py from flask import Flask from .views import account from .views import admin from .views import user app = Flask(__name__) app.register_blueprint(account.ac) app.register_blueprint(admin.ad) app.register_blueprint(user.us) .views -account.py -admin.py -user.py mamage.py from s8pro import app if __name__ == '__main__': app.run()
附件:项目模板示例
1小型项目示例 (点击下载)(提取码:huaw)