Flask基础知识点1

一、.基于装饰器的session访问控制,endpoint路由参数可以解决视图函数重名的情况。

下面我有一个简单的需求,就是一个网站有三个页面,分别是home、index和login界面,用户只有当登陆后才可以正常访问home和index页面,通过装饰器的方法来实现。接下来看代码

from flask import Flask, request, render_template, redirect, Markup, session

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


def wrapper(f):
    def inner(*args, **kwargs):
        if session.get("user"):
            ret = f(*args, **kwargs)
            return ret
        else:
            return redirect("/login")

    return inner


@app.route("/login", methods=("GET","POST"))
def login():
    if request.method == "GET":
        return render_template("login.html")
    if request.method == "POST":
        username = request.form.get("username")
        session["user"] = username
        return "登陆成功"

@app.route("/home", methods=("GET", "POST"))
@wrapper
def home():
    return "这是home界面的内容"

@app.route("/index")
def index():
    return "我是index界面的内容"

app.run()

当我们只对home视图函数加上认证装饰器时实现了我们的需求,但是如果你给index也加上认证装饰器时你就会发现Flask项目启动不起来了,会报一个这样的错误:


Flask基础知识点1
image.png

这是因为,当我们对一个以上的视图函数添加了认证装饰器后 ,认证装饰器会将视图函数名替换成装饰器的内层函数名inner,在内存中就会出现视图函数名重复的情况,这样Flask的路由装饰器装饰视图函数时就会报错,解决这个错误的方法就是给路由的endpoint参数指定视图函数名,即:

from flask import Flask, request, render_template, redirect, Markup, session

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


def wrapper(f):
    def inner(*args, **kwargs):
        if session.get("user"):
            ret = f(*args, **kwargs)
            return ret
        else:
            return redirect("/login")

    return inner


@app.route("/login", methods=("GET","POST"))
def login():
    if request.method == "GET":
        return render_template("login.html")
    if request.method == "POST":
        username = request.form.get("username")
        session["user"] = username
        return "登陆成功"

@app.route("/home",endpoint="home", methods=("GET", "POST"))
@wrapper
def home():
    return "这是home界面的内容"

@app.route("/index",endpoint="index")
@wrapper
def index():
    return "我是index界面的内容"

app.run()

二、Flask中的路由参数

  • @app.route()
@app.route(
    "/<age>"                  // 动态路由参数,默认是string,也可以是"/<int:age>"
    redirect_to = "/login"    //不经过视图函数直接重定向指定url
    defaults = {"age": 999}   //指定默认参数
    endpoint = "home"         //路由别名,用于反向生成URL,即: url_for('名称')
    methods = ("GET", "POST") //请求方式
    strict_slashes = False    //是否严格匹配url最后的"/",例:http://127.0.0.1:5000/home 和 
                             //http://127.0.0.1:5000/home/
    )

常用动态路由参数有以下五种,所有的路由系统都是基于以下对应关系来处理:

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

url_for的用法

from flask import Flask,url_for

app = Flask(__name__)

@app.route("/index/<int:age>",endpoint="index")
def index(age):
    url = url_for("index",age = age)
    print(url)      //    "/index/122"
    return "我是index界面的内容"

app.run()
  • app.add_url_rule()方法:比@app.route()多了一个 view_func=view_func参数,其他的相同。

三、Flask配置文件

1. 初始化Flask实例时的配置

app = Flask(_name_,template_folder="template",static_folder="static",static_url_path="/static")

  • static_url_path = "/static_folder" 访问静态目录文件时的地址 默认值是等于static_folder的名字,(应用场景描述:当后端static文件名修改后,加入前端页面使用了大量的之前的static路径,可以将static_url_path参数设置为老的,这样就可以不用修改前端代码了。)
  • static_folder = "static" 静态文件的存放路径
  • template_folder='templates' 模板路径
2. Flask实例的配置 app配置
  • 方式一、app.config["DEBUG"] = True
    PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)
  • 方式二、app.config.from_object(obj)
class obj():
    DEBUG = True
    SECERT_KEY = "123123"
  • 方式三、app.config.from_pyfile("settings.py")
    settings.py
DEBUG = True
SECERT_KEY = "123123"
  • 方式四、app.config.from_envvar("环境变量名称")
    PS:环境变量的值为python文件名称名称,内部调用from_pyfile方法
  • 方式五、app.config.from_json("json文件名称")
    PS: JSON文件名称,必须是json格式,因为内部会执行json.loads
  • 方式六、app.config.from_mapping({'DEBUG':True})
    PS:字典格式

四、Flask的蓝图

蓝图”和一个Flask应用对象很相似,但是并不是一个Flask应用对象。它是可以注册到Flask应用上的一系列操作(对于此的理解,后文会详细讲到)。使用“蓝图”,可以实现以下的一些功能:

  • 将Flask应用“分割”为一系列“蓝图”的集合,简化了大型应用工作的方式;
  • 在Flask应用上,以 URL 前缀和或子域名注册一个蓝图。可以以不同的URL多次注册一个蓝图;
  • 通过蓝图提供模板过滤器、静态文件、模板和其它功能。

第一步:蓝图的创建(蓝图的示例和Flask的实例参数一样)
add.py

from flask import Blueprint,render_template

bp = Blueprint("bp", __name__,
                   template_folder="blueprint_temp",
                   static_folder="blueprint_static",
                   static_url_path="/static2")

@bp.route("/add")
def add():
    return render_template("add.html")

第二步:注册蓝图:

from flask import  Flask
import add

app = Flask(\__name__)

app.register_blueprint(add.bp)

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

五、Flask里面的扩展,相当于django中的中间件

1.before_request 再请求进入视图函数之前作出处理 return None;before_request是顺序执行
2.after_request 在请求结束视图函数之后,返回客户端之前 ,要有参数和返回值,after_request是逆向执行
3.errorheadler(404) 自定制错误提示,自定义的函数必须有参数

  • before_request和after_request装饰器的使用
from flask import Flask, request, render_template, redirect, Markup, session, url_for

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


@app.before_request
def process_request1():
    print('process_request1')


@app.after_request
def process_response1(response):  # 必须有参数
    print('process_response1')
    return response  # 必须有返回值


@app.before_request
def process_request2():
    print('process_request2')


@app.after_request
def process_response2(response):  # 必须有参数
    print('process_response2')
    return response  # 必须有返回值


@app.route("/login", methods=("GET", "POST"))
def login():
    if request.method == "GET":
        return render_template("login.html")
    if request.method == "POST":
        username = request.form.get("username")
        session["user"] = username
        return "登陆成功"

app.run()

访问login视图函数后的控制台输出结果为:

process_request1
process_request2
process_response2
process_response1

通过代码的打印结果可以看出,before_request顺序执行;after_request逆向执行

  • errorhandler(404)的使用
@app.errorhandler(404)
def errors(code_or_exception):   //必须有参数
    return "错误"    //可以返回字符串,html,重定向等

六、闪现:flash

session存在在服务端的一个字典里面,session保存起来,取一次里面还是有的,直到你删除之后才没有了。

flash的本质:flash是基于session创建的,flash支持往里边放值,只要你取一下就没有了,相当于pop了一下。不仅吧值取走,而且吧session里的东西去掉。

flash的使用:get_flashed_messages()和flash("内容")

from flask import Flask,session,render_template,request,flash,get_flashed_messages
import flask_config

app = Flask(__name__) 

@app.route("/index")
def index():
    res = get_flashed_messages()
    if not res:
        res = [""]
    flash("你刚才访问了index")
    return render_template("index.html",msg=res[0])

@app.route("/home")
def index1():
    res = get_flashed_messages()
    if not res:
        res = [""]
    flash("你刚才访问了home")
    return render_template("index.html",msg=res[0])

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

七、Flask的send_file使用

from flask import Flask,send_file

app = Flask(__name__)

@app.route("/index", endpoint="index")
def index():
     return send_file(file_path)   //send_file()的作用是打开文件传输内容

app.run()

八、Flask的jsonify的使用

  • json.dumps的作用是序列化数据
  • jsonify的作用是将后端数据json序列化,打包一个 content-Type:application/json 返回给客户端
from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/index", endpoint="index")
def index():
     #return json.dumps({123:"34"})   //传给前端的是json数据,仅此而已!
     return jsonify({123:"34"}))    //序列化数据,将响应头的content-Type: 更改为application/json 
app.run()
上一篇:《编程的原则》重新发明车轮感悟之循序渐进


下一篇:基于事件驱动应用的福音-函数计算异步调用目标