flask框架总结

文章目录

  • flask框架总结
    • 原理
      • 请求上下文原理
      • flask握手原理
      • flask发送数据加密,解密原理
    • 快速启动flask服务
      • app.run()接受参数如下
      • app.route()装饰器接受参数如下
    • 动态路由参数
    • 处理请求方法
      • FBV 方法示例
      • CBV方法示例
    • flask响应三剑客
    • reqeust
    • 模板语法jinja2
      • for语法
      • if语法
      • safe过滤器
      • Markup
      • 传入函数名
      • 自定义标签
      • 自定义过滤器
      • extends标签
      • include标签
      • include和extend区别
      • 宏指令
    • session
    • flask配置
      • app配置
      • 初始化配置
    • flask蓝图
    • flask中间件
      • 自定义错误errorhandler
      • flask中flash闪现

flask框架总结

特点:短小精悍,支持三方组件,稳定性相对其他框架较差。
web服务端,基于socket制作

原理

flask框架总结_第1张图片
wsgi:应用程序网关接口
django使用的是uwsgi
flask使用的是werkzeug(wsgi封装)

请求上下文原理

在flask中reqeust和session都为公共变量,直接通过flask导入,而不是通过参数传入视图函数
实现原理是:
wsgi处理-》打包成ctx=RequestContext(包含reqeust,session)->ctx.push(将当前请求信息存入栈中)-》视图函数处理-》执行reqeust相关方法时,从栈中获取数据
{__storage__:{线程号:{"stack":[ctx]}},__ident_func__:get_ident}
get_ident为获取线程号的方法名

flask握手原理

websocket通信原理
后端
获取请求体中字符串Sec-WebSocket-Key,拿到key
用magic_string字符串与其拼接,使用sha1加密,再用base64加密
拼接响应头,添加Sec-WebSocket-Accept字段,发送给浏览器
前端浏览器
链接服务器,发送请求头,含Sec-WebSocket-Key字段
获取响应头,解密,校验握手是否成功

flask发送数据加密,解密原理

解密
浏览器send发送数据过来为bytes类型

  1. 第1位,固定\x81
  2. 第2位, 首先与127进行与运算 有0得0 data_length结果有3种情况
    情况一: <= 125 当前data_length就为数据长度 125(3-6为mask_key)
    情况二:==126 数据长度两位,3-4字节为数据长度 65535(5-8mask_key)
    情况三:==127 数据长度为八位,3-10字节为数据长度 2**64(11-14mask_key)
  3. 往后四位,为mask—key,为密钥,可以解密后面的字符串
    bytes = decode[i] ^ mask[i%4]
    每位用或运算和mask—key的四个数

加密

  1. 解码msg为bytes类型
  2. 第一位固定为\x81
  3. 计算程度,根据长度不同,打包的数据大小不同
    struct打包
    情况一: < 126 struct.pack("B",length)
    情况二: == 126 struct.pack("!BH",126,length)
    情况三: > 126 struct.pack("!BQ",127,length)
  4. 拼接发送

快速启动flask服务

from flask import Flask

app = Flask(__name__)  #在该模块中Flask标识,可以传入任意字符串

@app.route('/')   #装饰器第一个参数为路由
def index():
    return "hello world"  # 直接返回字符串到页面上

app.run()  # 启动flask

app.run()接受参数如下

run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
例如:
app.run(host="127.0.0.1",port=9527,debug=True)
debug为true时,每次修改代码后,自动重启服务

app.route()装饰器接受参数如下

@app.route('/hi2',endpoint="hi2",redirect_to="/",methods=("GET","POST"),defaults={"age":22})
def hi2(age):
    return redirect('/')

endpoint:函数标识,默认为函数名,在反向解析时使用url_for(‘hi2’)可以解析出url。 当函数重名时,只要endpoint不重名即可
redirect_to:不通过视图函数,直接重定向(永久重定向)
methods:允许请求方法,默认只允许GET,可以传入一个列表或元组
defaults:默认参数,默认传入视图函数的参数,视图函数必须要有参数来接受
strict_slashes:严格匹配,默认值为False,值为True时,地址末尾多一个斜杠也不允许访问

动态路由参数

可以使用<>方式添加变量名,同时视图函数也要接受参数,来匹配路由

默认参数类型是字符串

@app.route('/hi//')
def hi(normal,age):
    print(normal,age)
    return redirect('/')

处理请求方法

处理请求有CBV和FBV两种方式
FBV:在视图中,通过函数类处理请求
CBV:在视图中,通过类来处理请求

FBV 方法示例

通常我们使用函数加装饰器方法组成视图函数

@app.route('/')
def index():
    return "hello world"

等价于

def index2():
    return "hello world1"
app.add_url_rule("/index2",view_func=index2)

view_func为视图函数的函数名

CBV方法示例

from flask import views

def war(func):
    def inner(*args,**argv):
        print("inner")
        return func(*args,**argv)
    return inner

class Index3(views.MethodView):
    methods = ["GET","POST"]
    decorators = [war]
    def get(self):
        return "nice get"

    def post(self):
        return "nice post"
app.add_url_rule(rule="/test",view_func=Index3.as_view(name="index33"))

类需要继承views.MethodView,类中添加相应请求方法的处理函数(get方法请求,就添加名为get的函数)
methods:默认为只允许get方法访问
decorators: 将类中每个函数添加装饰器,每次执行函数时,自动依次执行装饰器
as_view:将类转换为相应视图函数,name为函数标识

flask响应三剑客

from flask import Flask,render_template,redirect,jsonify,send_file  
@app.route('/')  
def index():
    return "hello world"

@app.route("/login")
def login():
    return render_template('login.html')

@app.route('/hi')
def hi():
    return redirect('/')
    
@app.route("/hello")
def hello():
    return jsonify({"name":"xiaoming","age":16})
    
@app.route("/web")
def web():
    return send_file("./small.png")

直接返回字符串,类似于django的HttpResponse
render_template返回模板,类似于django的render
redirect重定向(默认302临时重定向),和django一样

jsonify返回json字符串,content-Type为Content-Type: application/json
send_file返回一个本地文件,根据文件不同content-Type不同

reqeust

reqeust为一个全局变量,获取请求信息,所有请求信息经过wsgi处理后转换为键值对形式存入字典中

from flask import request
@app.route('/')
def index():
    print(request.method)  #返回当前请求方法
    print(request.args)    #get携带的参数键值对(字典),get取值
    print(request.form)    #表单提交
的结果(字典),get取值 print(request.json) #数据格式application/json bytes类型 print(request.data) #request定义的格式不存在的 application/xiaowangba bytes类型的数组 print(request.values) #同时获得url携带参数和post请求获取的参数,get取值如果get和post请求参数重名时,取get请求参数的值因为先序列化form,后序列化args,args同名参数会将其覆盖 return "hello world"

request还有url,path等方法

模板语法jinja2

在django和flask中都使用了jinja2语法
变量语法 {{ msg }}
tag标签语法 逻辑代码 {% if %}

for语法

遍历

{% for stu in stu_list %}
{% endfor  %}

获取字典值时,可以使用下标,[],get方法

{{ student.name }}
{{ student["name"] }}
{{ student.get("name") }}

获取列表值时,可以使用下标方法或传入索引

 {{ student[0] }}
 {{ student.0 }}

if语法

条件判断

{% if session %}
{% elif session1 %}
{% else %}
{% endif %}

示例

{% if student.3 == 'female'  %}
    
{% else %}
    
{% endif %}

safe过滤器

将变量中字符串渲染成标签
{{ msg|safe }}
默认情况,字符串不能直接被渲染成字符串,必须使用safe过滤器

Markup

类似于safe,只不是在后端执行

from flask import Markup
@app.route('/1')
def index1():
    text_tag = "

我是p标签

" text_tag = Markup(text_tag) return render_template("index.html",msg=text_tag)

将字符串转换为标签,在页面上渲染

传入函数名

后端也可以直接向前端传入函数名,前进接受后直接使用
python

def add(a,b):
    return a+b

@app.route('/2')
def index2():
    return render_template("index.html",add=add)

html

{{ add(1,2) }}

自定义标签

自定义全局函数
python

@app.template_global()
def add_tag(*args):
    return sum(*args)

不需要通过参数传入模板,直接在模板中调用
html

{{ add_tag([1,2,3]) }}

自定义过滤器

自定义全局过滤器
python

@app.template_filter()
def jiou(num):
    return "奇数" if num % 2 else "偶数"

html

{{ 5|jiou }}

extends标签

继承父模板框架,必须卸载最上方
block:在index.html中为占位符,在index2.html中为实际内容
index.html




    
    Title


{% block container %}
    

默认显示内容,没有block时显示

{% endblock %}

index2.html

{% extends "index.html" %}
{% block container %}
    

新内容

{% endblock %}1

include标签

include:导入代码块,将代码块导入到网页中
index.html




    
    Title


{% include "login.html" %}



login.html




    
    登录


登录


include和extend区别

include:用于多个html页面,有相同代码部分,这部分用include导入,比如导入小广告
extends:用户同一主题的页面,用相同主题,只修改block部分,其他部分不变。extends必须写在页面开头,配合block使用。模板继承

宏指令

创建标签,宏指令




    
    登录


登录
{% macro create_tag(name) %}
    

{{ name }}

{% endmacro %} {{ create_tag("xiaoming") }} {{ create_tag("wanghua") }}

相当于html中的函数,传入参数,执行参数

session

session和cookie用户信息的缓存,cookie一般存放在用户端,session一般存放在服务端
但是flask原生session是将用户信息存放在cookie中,也就是用户端

from flask import session

app = Flask(__name__)
app.secret_key = "this_is_any_string"
@app.route('/3')
def index3():
    session["name"] = "xiaoming"  #添加一个session键值对
    print(session["name"])        #获取session值
    return render_template("test.html")

注意:首先导入session,其次必须要secret_key
session存放在cookie中,键session,值(secret_key经过md5序列化+时间戳+session字典中的键值)

flask配置

app配置

方法一:
使用字典方式设置

from flask import Flask
app = Flask(__name__)
app.config["DEBUG"]=True

方法二:
使用对象方式

obj为类  
class obj():
    DEBUG:True
    SECERT_KEY="1234567890" 
app.config.from_object(obj)

在对象中设置值

初始化配置

flask示例初始化配置

app = Flask(__name__) 
'''
def __init__(
    self,
    import_name,  #该参数用来标识实例的(用来区分是否是一个实例化对象,request等)
    static_url_path=None,  #访问静态文件的url  默认等于static_folder
    static_folder="static",  #静态文件夹
    static_host=None,  #远程访问静态文件(静态文件夹不在本地)必须和host_matching一起用
    host_matching=False,
    subdomain_matching=False,
    template_folder="templates",  #指定模板文件夹
    instance_path=None,
    instance_relative_config=False,
    root_path=None,
):
'''

flask蓝图

flask蓝图相当于不能运行的flask实例,用来做插件用
student_add.py

from flask import Blueprint
stu_add = Blueprint("stu_add",__name__)
@stu_add.route("/student_add",methods=("GET",'POST'))
def student_add():
    return render_template("student_add.html")

参数一位蓝图实例名,用来区分蓝图与蓝图
参数二蓝图空间标识
注意:蓝图默认static和template和app默认存储位置相同

注册蓝图
main.py

from student_add import stu_add
app.register_blueprint(stu_add.stu_add)

即可使用
蓝图中的视图函数名与app视图函数名相同时不会出错,但url_for反向解析时会报错

flask中间件

flask使用两种装饰器类似于django中的中间件

@app.before_request
def is_login():
    white_list = ['/login',]
    if request.path in white_list:
        return None
    if session.get("is_login") and session["is_login"] + 3000*60 > time.time():
        return None
    else:
        return redirect('/login')
        
@app.after_request
def go(res):
    print("after")
    return res
  1. before_request在每次进入任何视图函数前使用,after_request在每次出视图函数前使用 2. after_request必须传入一个参数response,返回这个参数
  2. before_request执行顺序,代码顺序before1->before2,在请求进入视图函数之前作出处理
  3. after_request执行顺序,从后向先执行 after2->after1 代码在前面的,执行顺序靠后
  4. 正常执行顺序:before1->before2->after2->after1
  5. 当before2出现异常时,before1->after2->after1

自定义错误errorhandler

可以自定义404错误

@app.errorhandler(404)
def errors(*args):
    print(args)
    return "没有找到当前页面"

也可以自定义错误页面

flask中flash闪现

flash存一次,取一次后就销毁,不占空间。
通常用来上一个位置使用

from flask import flash,get_flashed_messages

@app.route("/home")
def home():
    res = get_flashed_messages()
    print(res)
    flash("home")
    return render_template("home.html",loc = res)

@app.route("/music")
def music():
    res = get_flashed_messages()
    print(res)
    flash("music")
    return render_template("music.html",loc = res)

你可能感兴趣的:(Django学习)