特点:
短小精悍,可扩展性强
依赖wsgi:werkzurg
werkzurg示例:
from werkzeug.wrappers import Request, Response from werkzeug.serving import run_simple def run(environ,start_response): return [b"asdfasdf"] if __name__ == '__main__': run_simple('localhost', 4000, run)
最简单的实现形式
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)
正常的内部实现形式
#访问index则可以得到Hello World from flask import Flask app = Flask(__name__) @app.route("/index") def run(): return "Hello World" if __name__ == "__main__": app.run()
九行代码实现网页
实现一个登陆验证的功能:
from flask import Flask,render_template,request,redirect,session app = Flask(__name__) #一般用__name__,但是用其他只要是字符串都行 app.secret_key = "asdfsg" #给session加密的盐 @app.route("/login",methods=["GET","POST"]) def login(): if request.method == "GET": return render_template("login.html") user = request.form.get("user") #request.args相当于request.GET,request.form相当于request.POST pwd = request.form.get("pwd") if user=="xxx" and pwd=="xxx": session["user"] = user #flask的session其实是cookie,但是加了密 return redirect("/index") else: return render_template("login.html",error="用户名或密码错误") #或者可以写成**{error:"用户名或密码错误"} @app.route("/index") #不写methods默认只接受GET请求 def index(): user = session.get("user") if not user: return redirect("/login") return render_template("index.html") if __name__ == "__main__": app.run()
flask的session是把数据以加密的方式保存在用户的浏览器中。
静态文件和模板路径可以在app = Flask(__name__, xxxxxx) 里配置。
一、配置文件
from flask import Flask app = Flask(__name__) app.config #里面保存所有配置信息,是一个字典形式的数据 app.config.from_object("settings.Dev") #修改配置信息,将Dev类中的静态字段的值赋值给配置文件中同名的值
实现源码:
class Flask(xxx): def from_object(self, obj): if isinstance(obj, string_types): obj = import_string(obj) for key in dir(obj): if key.isupper(): self[key] = getattr(obj, key)
import importlib def import_string(obj): p, c = obj.rsplite(".", maxsplit=1) m = importlib.import_module(p) cls = getattr(m, c) return cls
二、路由系统
from flask import url_for @app.route("/index", methods=["GET",], endpoint="n") #如果不写endpoint,则默认是函数名index def index(): print(url_for("n")) #反向生成url,返回“/index” return "index"
url中传参数:
@app.route("/index/<nid>",methods=["GET",]) def index(nid): print(nid) #得到参数 print(url_for("index",nid=123)) #得到 /index/nid
1、路由系统的源码实现:
class Flask: def route(self,rule,**options): def decorator(f): endpoint = options.pop('endpoint',None) self.add_url_rule(rule,endpoint,f,**options) return f return decorator #所有这个装饰器实际上就是执行add_url_rule函数
app.route(xxx)的源码
def add_url_rule(self, rule, endpoint=None, view_func=None, provide_automatic_options=None, **options): if endpoint == None: endpoint = _endpoint_from_view_func(view_func) #返回函数的__name__,即函数名 。。。。。。 if view_func is not None: old_func = self.view_functions.get(endpoint) #这是一个字典,一开始是空,会加入endpoint和函数的对应关系 if old_func is not None and old_func != view_func: #如果这个endpoint已经对应了一个函数,并且这个函数和当前要绑定的函数不一样,则报错 raise 错误 self.view_functions[endpoint] = view_func #否则就在view_functinos字典中加入这个对应关系
add_url_rule源码
2、参数:
subdomain 子域名访问 app.config["SERVER_NAME"] = xxxx @app.route("/",subdomain="user") #访问“user.xxx"调用 def index(): return redirect_to 永久重定向 strict_slashes=False 地址后面加上/也可以访问
3、CBV
from flask import views class UserView(views.MethodView): #methods = ["GET",] 加上这句就限制可以接受的方法 #decorators = [wrappers,] 对每一个函数加上一个装饰器,也可以在每个函数上单独加 def get(self,*args,**kwargs): return app.add_url_rule("/user",None,UserView.as_view("endpoint"))
4、自定义正则
from wekzerg.routing import BaseConverter class RegexConvertoer(BaseConverter): def __init__(self,map,regex): super(RegexConverter,self).__init__(map) self.regex = regex def to_python(self,value): #路由匹配成功后把value传递给视图函数 return value def to_url(self,value): #反向解析url时 val = super(RegexConverter,self).to_url(value) return val @app.route("/index/<regex('/d+'):val>") def index(val): print(val) return xxx
三、视图
四、请求相关
request.method request.args request.form request.files request.headers request.cookies
五、响应相关
return "index" return redirect("/index") return render_template("index.html") dic = {"p":1} return jsonify("dic") #自动序列化 #除了重定向都可以设置响应头 from flask import make_response obj = make_response("index") #obj = make_response(jsonify(dic)) #obj = make_response(render_template("index.html")) obj.headers["xxx"] = 123 #设置cookie obj.set_cookie("key","value")
**三种方式实现登录验证
方式一:在每个视图函数中加入判断(不用)
方式二:在需要验证的视图函数前加一个装饰器
import functools def auth(func): @functools.wraps(func) #这样装饰器所修饰的函数的信息不会被改变,避免出现函数名都是inner,导致反向解析url报错的问题 def inner(*args,**kwargs): #省略 ret = func(*args,**kwargs) return ret return inner @app.route("/index", methods=["GET",]) @auth def index(): return render_template("index.html")
方式三:before_request
@app.before_request def auth(): if request.path == "/login": return None #return None就表示pass if session["user"]: return None return redirect("/login") @app.route("/login", methods=["GET", "POST",]) def login(): if request.method == "post": session["user"] = request.form.user else: return render_template("login.html")
六、模板渲染
--解除标签限制两种方式:在视图中Markup, 在模板中 |safe
--函数调用两种方式:直接函数名加括号, 或者在视图中定义函数时加上@app.template_global()装饰器,可以直接调用
--模板的继承同django,extends和block
七、session
flask的session操作和操作字典一样,在响应时将session数据序列化并加密,在请求时将数据解密并反序列化成字典。
八、闪现
本质就是把数据先保存在session中,取数据时使用pop
from flask import flash,get_flash_messages app = Flask(__name__) @app.route("/test1") def test1(): flash("数据1", category="info") #category是分类,可以不写,默认是messages " @app.route("/test2") def test2(): print(get_flash_messages(category="info")) #可以不加参数
九、中间件
flask没有提供中间件功能,但是可以通过替换app.__call__方法来实现中间件的作用,还可以通过before_request和after_request实现
def 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.__call__ = MiddleWare(app.__call__) app.run()
十、特殊的装饰器
@before_request @after_request @template_filter() @template_global()@errorhandle(404)