Flask的基础二

一、session

除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。

  • 设置:session['username'] = 'xxx'
  • 取值:session.get['username']
  • 删除:session.pop('username', None)
from flask import Flask
from flask import render_template
from flask import session
from flask import request
from flask import redirect

app = Flask(__name__)

app.config.from_mapping({"SECRET_KEY":"value"})

@app.route("/login",methods=["GET","POST"])
def login():
    if request.method == "POST":
        username = request.form.get("username")
        password = request.form.get("password")
        if username == "xiaoming" and password == "123":
            # 登陆成功后设置session
            session["userinfo"] = {"name":username}
            return redirect("/")
    return render_template("login.html")

@app.route("/")
def index():
    # 获取session
    print(session["userinfo"])
    return "首页"

if __name__ == '__main__':
    app.run()

 

二、flash 闪现

闪现的作用:flash设置值只能取一次

闪现的原理:利用session设置值,通过pop的方法删除并返回值,取值的时候调用session.pop()的方法将值放到flashes中,请求还在取值都从flashes中获取

'''
存一次只能取一次值,用session模拟闪现
'''
from flask import Flask,session

app = Flask(__name__)
app.secret_key = "key"      # 设置session需要设置secret_key

@app.route("/set")
def set():
    session['name'] = "xiaoming"
    return "Set name"

@app.route("/get")
def get():
    # 删除session的键值对并取值
    name = session.pop("name","")
    print(name)
    return name


if __name__ == '__main__':
    app.run()
session模拟flash
# 设置值
flash(message, category='message')

# 获取值
get_flashed_messages(with_categories=False, category_filter=[])
from flask import Flask,flash,get_flashed_messages

app = Flask(__name__)
app.secret_key = "key"

@app.route("/set")
def set():
    flash("xiaoming")   # 设置值
    flash(18,"age")     # 参数:message,分类
    return "flash设置值"

@app.route("/get")
def get():
    # 取值
    name = get_flashed_messages()  
    
    # 按分类取值category_filter=[]
    age = get_flashed_messages(category_filter=["age"])
    print(name)
    print(age)
    return "GET"

if __name__ == '__main__':
    app.run()

 

三、中间件

app.run()        #程序的入口

run_simple(host, port, self, **options)        # run的本质是调用run_simple
# host == ip
# port == 端口
# self == app

# 执行了self() 相当于执行app(),调用app的__call__方法
# app.__call__

def __call__(self, environ, start_response):
    return self.wsgi_app(environ, start_response)

# 相当于执行 app.wsgi_app(environ, start_response)
app.run的源码流程
'''
中间件的实现
'''

from flask import Flask

app = Flask(__name__)

class Middleware(object):
    def __init__(self,old_wsgi_app):
        # 原来的wsgi_app
        self.wsgi_app= old_wsgi_app

    def __call__(self, *args, **kwargs):
        print("项目启动之前")
        # wsgi_app是原来的wsgi_app
        ret = self.wsgi_app(*args, **kwargs)
        print("项目启动之后")
        return ret



if __name__ == '__main__':
    # 将旧的app.wsgi_app赋值给新的app.wsgi_app
    app.wsgi_app = Middleware(app.wsgi_app)
    app.run()

'''
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
项目启动之前
127.0.0.1 - - [28/Dec/2018 16:43:27] "GET / HTTP/1.1" 404 -
项目启动之后
'''

 

四、特殊的装饰器

@app.before_first_request # 第一次请求
@app.before_request # 每一次请求
@app.after_request # 每一次响应

注意:before_request有返回值,不走视图函数,直接走after_request
@app.template_global()
@app.template_filter()
@app.errorhandler(404)

'''
自定义装饰器实现登陆认证
'''

from flask import Flask
from functools import wraps
from flask import url_for
from flask import session
from flask import render_template
from flask import request,redirect


app = Flask(__name__)
app.secret_key = "key"

# 自定义装饰器
def Auth_decorator(func):
    @wraps(func)
    def inner(*args,**kwargs):
        # 访问是否携带认证,否则跳转都登陆页面
        if not session.get("user",""):
            return redirect("login")
        ret = func(*args,**kwargs)
        return ret
    return inner



# 登陆
@app.route("/login",endpoint="login",methods=["GET","POST"])
def login():
    if request.method == "POST":
        username = request.form.get("username")
        password = request.form.get("password")
        if username == "xiaoming" and password == "123":
            # 登陆成功后设置session
            session["user"] = username
            return redirect(url_for("myhome"))
    return render_template("login.html")

# 登陆成功后跳转的页面
@app.route("/home",endpoint="myhome")
@Auth_decorator
def home():
    return "登陆成功的HOME页面"

if __name__ == '__main__':
    app.run()
自定义登陆认证的装饰器
# 模板的全局装饰器
@app.template_global()
def mysum(n1,n2):
    return n1+n2

# HTML
{{ mysum(10,5) }}
@app.template_global()
# 模板的筛选器
@app.template_filter()
def myfilter(data):
    return data[::2]

# HTML
{{ "today hello" | myfilter() }}
模板的筛选器
# 路径不存在跳转到指定页面的装饰器
@app.errorhandler(404)
def error_page(error):
    return render_template("error404.html")
路径不存在返回页面

 

五、路由的实现原理

不能有多个endpoint指向同一个视图函数,内部是{'endpoint':"view_func"}

app.route()
# 执行route函数
route(self, rule, **options)    
# self == app
# rule == 路由

# 返回decorator函数
return decorator

# decorator函数,传入视图函数
def decorator(f):
    endpoint = options.pop('endpoint', None)
    self.add_url_rule(rule, endpoint, f, **options)
    return f

# 调用add_url_rule(路由,endpoint,视图函数)
def add_url_rule(self, rule, endpoint=None, view_func=None,provide_automatic_options=None, **options):
    # endpoint不能有多个视图函数,否则抛出异常
    if view_func is not None:
        old_func = self.view_functions.get(endpoint)
        if old_func is not None and old_func != view_func:
            raise AssertionError('View function mapping is overwriting an '
                                 'existing endpoint function: %s' % endpoint)
        self.view_functions[endpoint] = view_func
route源码流程
'''
根据路由原理创建Flask项目
'''
from flask import Flask

# 实例化Flask对象
app = Flask(__name__)

def index():
    return "这是首页"

# 调用app.route的核心方法,实行app.route
app.add_url_rule("/",view_func=index)

if __name__ == '__main__':
    app.run()

六、CBV编程

1.类继承views.MethodView
2.装饰器修饰的列表 decorators = []
3.指定路由和类 app.add_url_rule

from flask import Flask
from flask import views

app = Flask(__name__)

class MyView(views.MethodView):
    # decorators = []               # 存放装饰器的列表
    # methods = ["GET","POST"]      # 请求方式列表,用于限制的

    def get(self):
        return "GET"

    def post(self):
        return "POST"

app.add_url_rule("/",view_func=MyView.as_view(name="index"))

if __name__ == '__main__':
    app.run()

七、自定义路由正则匹配

from flask import Flask,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 value

    def to_url(self, value):
        '''
        使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
        :param value:
        :return:
        '''
        val = super(RegexConverter,self).to_url(value)
        return val

# 添加到flask中
app.url_map.converters['regex'] = RegexConverter

@app.route("/index/<regex('d+'):id>")
def index(id):
    print(url_for('index',id='123'))
    print(type(id))
    return "{}".format(id)

if __name__ == '__main__':
    app.run()
原文地址:https://www.cnblogs.com/st-st/p/10186826.html