yyz notes yyz notes
首页
  • RBAC权限设计
  • 架构图标设计
  • 账号体系
  • python基础
  • python高级
  • python模块
  • python设计模式
  • python数据结构与算法
  • django
  • django-DRF
  • flask
  • 直接设计开源pip包
  • 直接设计开源项目
  • python示例题/脚本
  • python面试题
  • golang基础
  • golang高级
  • golang常用组件
  • gin框架
  • es6
  • javascript
  • react
  • vue
  • TypeScript
  • mysql
  • redis
  • minio
  • elasticsearch
  • mongodb
  • 消息队列
  • 自动化测试
  • 操作系统

    • linux
    • windows
  • nginx
  • docker
  • k8s
  • git
  • ldap
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

益章

可乐鸡翅
首页
  • RBAC权限设计
  • 架构图标设计
  • 账号体系
  • python基础
  • python高级
  • python模块
  • python设计模式
  • python数据结构与算法
  • django
  • django-DRF
  • flask
  • 直接设计开源pip包
  • 直接设计开源项目
  • python示例题/脚本
  • python面试题
  • golang基础
  • golang高级
  • golang常用组件
  • gin框架
  • es6
  • javascript
  • react
  • vue
  • TypeScript
  • mysql
  • redis
  • minio
  • elasticsearch
  • mongodb
  • 消息队列
  • 自动化测试
  • 操作系统

    • linux
    • windows
  • nginx
  • docker
  • k8s
  • git
  • ldap
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • python基础

  • python高级

  • python模块

  • python设计模式

  • python数据结构与算法

  • django

  • django-DRF

  • flask

    • flask基础

      • flask基础(1)
        • 链接资料
        • day01
        • 作业:
        • day02
        • 内容回顾
        • 1. 装饰器
        • 2. 谈谈你对面向对象的认识?
          • 今日内容
          • 1、配置文件
          • a.创建一个配置文件settings.py
          • b. 在flask中使用配置
          • 其他方式(更多配置)
          • 2、路由
          • 1. 添加路由的二种方式
          • 2.反向生成url(url_for)/设置路由的别名(endpoint)
          • 3.传参数/自定义正则参数
          • 4.@app.route和app.add_url_rule参数
          • 3、flask视图中使用装饰器
          • 4、视图
          • 1. FBV
          • 2.CBV
          • 5、请求和响应
          • 6、模板的使用
          • 7、flask中的session
          • 8、特殊装饰器
          • 其他常见的装饰器
          • 9、消息闪现
          • 10、flask中间件
          • 11、蓝图(django的路由分发)
          • 12、补充
          • 1.生成项目依赖的方式
          • 13、函数/方法
      • flask基础(2)
    • flask项目

  • 自己设计开源pip包

  • 自己设计开源项目

  • python小示例

  • python面试题

  • python
  • flask
  • flask基础
YiZhang-You
2023-05-20
目录

flask基础(1)

# 链接资料

老男孩:<https://www.cnblogs.com/wupeiqi/articles/7552008.html>
flask官网插件:<https://flask.palletsprojects.com/en/2.1.x/extensions/>
flask中文官网:<https://flask.net.cn/>
flask w3cschool:<https://www.w3cschool.cn/flask/flask_message_flashing.html>
<http://www.coolpython.net/flask_tutorial/deep-learn/what-is-wsgi.html>
1
2
3
4
5

# day01

谈谈对pythonWeb框架:

  • django:大而全,内部提供,ORM、Admin、中间件、From、ModelForm、Session、缓存、信号、CSR等
  • flask:短小精悍,可扩展强,第三方组件丰富。
  • tornado:短小精悍+异步非阻塞
  • 其他:
    • web.py (opens new window)
    • bottle.py (opens new window)

wsgi通信

  • django,wsgiref

  • flask,werkzurg

    from werkzeug.wrappers import Request, Response
    from werkzeug.serving import run_simple
    
    @Request.application
    def hello(request):
        return Response('Hello World!')
    
    if __name__ == '__main__':
    
        run_simple('localhost', 4000, hello)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

# 作业:

作业:

    1. 路飞

    2. Flask
        - 装饰器实现
            - 位置
            - url起别名(不能重复)
        - 类似django中间件的东西:before_request装饰器

    3. 上下文预习:
        a. threading.local
        b.
            functools.wraps
            functools.partial
        c. 面向对象封装

        d. 面向对象中:
            __setattr__
            __getattr__
            __delattr__
    4. 预习:
        <http://www.cnblogs.com/wupeiqi/articles/7552008.html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# day02

# 内容回顾

# 1. 装饰器

问题:什么是装饰器?
        问题:手写装饰器
        问题:装饰器都在哪里用过?

        import functools

        def wapper(func):
            @functools.wraps(func)  # 使用__name__可以返回原函数名,不使用的话没有
            def inner(*args,**kwargs):
                return func(*args,**kwargs)
            return inner
        """
        1. 执行wapper函数,并将被装饰的函数当做参数。 wapper(index)
        2. 将第一步的返回值,重新赋值给  新index =  wapper(老index)
        """
        @wapper
        def index(a1):
            return a1 + 1000

        @wapper
        def order(a1):
            return a1 + 1000

        print(index.__name__)
        print(order.__name__)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 2. 谈谈你对面向对象的认识?

- 封装:
        - 将同一类方法分为一类:方法封装到类中
        - 将方法中共同的参数封装到对象中:把共用值封装到对象中。

        情况:
            a. BaseReponse
                def index(a1,a2,a3,a4,a5,a6,a7):
                    pass

                # 用户类实现
                class Foo(object):
                    def __init__(self,a1,a2,a3,a4,a5,a6,a7):
                        self.a1 = a1
                        self.a2 = a2
                        self.a3 = a3
                        self.a4 = a4
                        self.a5 = a5
                        self.a6 = a6
                        self.a7 = a7

                def index(obj):
                    pass
            b. 给了一些值,将数据加工: django 自定义分页

                class Foo(object):
                    def __init__(self,a1,a2,a3,a4,a5,a6,a7):
                        self.a1 = a1
                        self.a2 = a2
                        self.a3 = a3
                        self.a4 = a4
                        self.a5 = a5
                        self.a6 = a6
                        self.a7 = a7

                    def 金条(self):
                        return self.a1 + self.a2

                    def 手表(self):
                        return self.a1 + self.a7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# 今日内容

# 1、配置文件

# a.创建一个配置文件settings.py (opens new window)

class BaseConfig(object):
    DEBUG = True  # 公共配置
    SECRET_KEY = "asudflkjdfadjfakdf"

class ProductionConfig(BaseConfig):
    """生产环境"""
    DEBUG = False

class DevelopmentConfig(BaseConfig):
    """开发配置"""
    pass

class TestingConfig(BaseConfig):
    """测试环境"""
    pass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# b. 在flask中使用配置

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 "f

if __name__ == '__main__':
    app.run()
1
2
3
4
5
6
7
8
9
10
11
12
13

# 其他方式(更多配置)

# 更多配置:<https://www.cnblogs.com/wupeiqi/articles/7552008.html>

方式一:
    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目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 2、路由

# 1. 添加路由的二种方式

多看源码

from flask import Flask, render_template, redirect

app = Flask(__name__)

"""
1. 执行decorator=app.route('/index',methods=['GET','POST'])
2. @decorator
     - decorator(index)

# 内部执行的方法
def decorator(f: F) -> F:
    endpoint = options.pop("endpoint", None)
    self.add_url_rule(rule, endpoint, f, **options)
    return f  # 返回函数名

return decorator
"""

# 路由方式一(*):
@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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 2.反向生成url(url_for)/设置路由的别名(endpoint)

通过添加endpoint('别名')参数设置别名,默认为函数名。

通过url_for('别名','参数')得到路由url

from flask import Flask, render_template, redirect, url_for

app = Flask(__name__)

"""
通过添加endpoint参数设置别名,默认为函数名,通过url_for('别名')得到路由url
"""

@app.route('/index1', methods=['GET', 'POST'], endpoint='n1')  # <http://127.0.0.1:5000/index1>
def index():
    v1 = url_for('n1')
    v2 = url_for('n2')  # 反向生成url
    v3 = url_for('logout')
    print(v1, v2, v3)  # /index1 /login1 /logout1
    return "Index"

@app.route('/login1', methods=['GET', 'POST'], endpoint='n2')
def login():
    return "login"

@app.route('/logout1', methods=['GET', 'POST'])
def logout():
    return "logout"

if __name__ == '__main__':
    app.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 3.传参数/自定义正则参数

  • @app.route('/user/')
  • @app.route('/post/int:post_id')
  • @app.route('/post/float:post_id')
  • @app.route('/post/path:path')
  • @app.route('/login', methods=['GET', 'POST'])

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

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}
1
2
3
4
5
6
7
8
9

上面的5种类型有时候满足不了需求,所以就有了自定义路由

a.编写自定义路由匹配规则,并把新添加的规则放入url_map中

# 1
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中的参数(val:是方向生成url的值)
        @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"
        :param value:
        :return:
        """
        val = super(RegexConverter, self).to_url(value)
        return val

# 2
app.url_map.converters['xxx'] = RegexConverter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 4.@app.route和app.add_url_rule参数

rule,                       # URL规则

view_func,                  # 视图函数名称

defaults=None,              # 默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数(当需要给视图函数提供参数的时候)
	@app.route('/index',defaults={'k':'123'})
	def index(k):
        print(k)  # 123

endpoint=None,              # 名称,用于反向生成URL,即: url_for('名称','参数')

methods=None,               # 允许的请求方式,如:["GET","POST"]

strict_slashes=None,        # 对URL最后的 / 符号是否严格要求,(django中一样)
      如:
          @app.route('/index',strict_slashes=False),
               访问 <http://www.xx.com/index/> 或 <http://www.xx.com/index均可>
          @app.route('/index',strict_slashes=True)
               仅访问 <http://www.xx.com/index>

redirect_to=None,           # 重定向到指定地址 当访问/index的时候自动跳转到/home路由上面
      如:
          @app.route('/index/<int:nid>', redirect_to='/home/<nid>')  # 重定向到路由
          def func(adapter, nid):
             return "/home/888"
          @app.route('/index/<int:nid>', redirect_to=func)  # 重定向到函数

subdomain=None,             # 获取子域名访问
	# 示例一
    app = Flask(__name__)
    app.config['SERVER_NAME'] = 'oldboy.com:5000'  # 服务器地址

    """
    www.baidu.com
    aab.baidu.com  # 子域名aab,www,通过配置获取到子域名
    1、添加服务器配置
        app.config['SERVER_NAME'] = 'oldboy.com:5000'  # 服务器地址
    2、在route中添加subdomain='username'
        def func(username)  # 接收到子域名
    """
    @app.route("/dynamic", subdomain="<username>")
    def xxxxxxx(username):
        print(username)
        return 'xxxxx'

	# 示例二
	from flask import Flask, views, url_for

    app = Flask(import_name=__name__)
    app.config['SERVER_NAME'] = 'wupeiqi.com:5000'

    @app.route("/", subdomain="admin")
    def static_index():
        return "static.your-domain.tld"

    @app.route("/dynamic", subdomain="<username>")
    def username_index(username):
        return username + ".your-domain.tld"

    if __name__ == '__main__':
        app.run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

# 3、flask视图中使用装饰器

使用装饰器的时候,添加到路由的下面,并在定义装饰器的时候加上@functools.wraps(func),不加的话会默认返回inner函数(使用name可以查看), 如果直接访问inner,没有访问到原来的index(),order(),就会报错

from flask import Flask, render_template, redirect

app = Flask(__name__)
import functools

"""
使用装饰器的时候,添加到路由的下面,并在定义装饰器的时候加上@functools.wraps(func),不加的话会默认返回inner函数(使用__name__可以查看),
如果直接访问inner,没有访问到原来的index(),order(),就会报错
"""
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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 4、视图

# 1. 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

# FBV
@app.route('/xxxx', methods=['GET', 'POST'])
@wapper
def index():
    return "Index"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 2.CBV

# CBV
# 方式一
"""
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,这里的name就和route(endpoint反向生成一样)
"""

# 方式二
class IndexView(views.MethodView):
    methods = ['GET','POST']  # 支持方法
    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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 5、请求和响应

使用时需要导包from flask import request

信息看官网:<https://flask.net.cn/quickstart.html#id14>
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  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'))  # 设置返回的cookie,headers等
    # 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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 6、模板的使用

Jinja2官网:<http://docs.jinkan.org/docs/jinja2/>
Jinja2基本使用:<https://www.cnblogs.com/ryxiong-blog/articles/11170889.html>
1
2

1、模板的使用

Flask使用的是Jinja2模板,所以其语法和Django无差别

2、自定义模板方法

Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,如:

flask可以传递函数

传值:
	@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)
使用:
	    <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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

全局:每个模板都可以使用这个函数

@app.template_global()
def sbbbbbbb(a1, a2):
    """
    每个模板中可以调用的函数
    :param a1:
    :param a2:
    :return:
    """
    return a1 + a2
1
2
3
4
5
6
7
8
9

# 7、flask中的session

更多操作示例:<https://www.cnblogs.com/wupeiqi/articles/7552008.html>
1

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

  • 设置:session['username'] = 'xxx'
  • 删除:session.pop('username', None)

flask中的session继承了字典,所以字典有的方法session都有,flask是把session存入cookies中,本地不存。

a.设置一把盐,和django一样 app.secret_key = 'sadfasdfasdf'

b.对session进行添加获取删除等操作

"""
1. 请求刚刚达到
    ctx = RequestContext(...)
          - request
          - session=None
    ctx.push()
        ctx.session = SecureCookieSessionInterface.open_session

2. 视图函数

3. 请求结束
    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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 8、特殊装饰器

常见装饰器详细说明:<http://www.coolpython.net/flask_tutorial/basic/flask-decorator-hook.html>
1
  • @app.before_request 执行视图函数之前(从上到下)
  • @app.after_request 执行视图函数之后(从下到上)
  • 如果before_request有返回值就不执行后面的视图函数和django类似

其实就是把装饰的函数放入列表中,after_request就列表反转了一下

示例一:

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"

if __name__ == '__main__':
    # app.__call__  # 最先调用call方法
    app.run()

# 前1 前2  视图函数x1 后2 后1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

示例二:

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"

if __name__ == '__main__':
    app.__call__
    app.run()
# 前1 后2 后1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

示例三:接口校验是否登录

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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 其他常见的装饰器

@app.before_first_request  # 第一次请求
def before_first_request1():
    print('before_first_request1')

@app.before_request   # 执行视图之前执行从上到下
def before_request1():
    Request.nnn = 123
    print('before_request1')

@app.after_request  # 执行视图之后执行从下到上
def after_request1(response):
    print('before_request1', response)
    return response

@app.errorhandler(404)  # 错误页面装饰器,有错误的时候执行
def page_not_found(error):
    return 'This page does not exist', 404

@app.template_global()  # 模板装饰器,可以在所有的模板中使用
def sb(a1, a2):
    return a1 + a2

@app.template_filter()  # 过滤装饰器
def db(a1, a2, a3):
    return a1 + a2 + a3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 9、消息闪现

<https://www.w3cschool.cn/flask/flask_message_flashing.html>
1

flask 提供了一个非常简单的方法来使用闪现系统向用户反馈信息。1、闪现系统使得在一个请求结束的时候记录一个信息,2、并且在下次(且仅在下一次中)请求时访问它返回信息,并删除掉记录,这通常与布局模板结合使用以公开信息。

Flask 模块包含 flash()** 方法。它将消息传递给下一个请求,该请求通常是一个模板。**

flash(message, category)  # 设置
1

其中,

  • message 参数是要闪现的实际消息。
  • category 参数是可选的。它可以是“error”,“info”或“warning”。类别可以在访问的时候通过类别去过滤

为了从会话中删除消息,模板调用 get_flashed_messages()。

get_flashed_messages(with_categories, category_filter)  # 获取并删除
1

两个参数都是可选的。如果接收到的消息具有类别,则第一个参数是元组。第二个参数仅用于显示特定消息。

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)
    data = get_flashed_messages(category_filter=['x1'])
    print(data,222)
    return "视图函数x2"

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

"""
['我要上向龙1', '我要上向龙1']
['我要上向龙1', '我要上向龙1'] 222
[]
[] 222
 当访问第二次的时候,就为空了 ,只保存一次,调用得到后就删掉其实就是在内部删掉了session.pop()
 用session也可以做就是session.pop
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 10、flask中间件

Flask的中间件的性质,就是可以理解为在整个请求的过程的前后定制一些个性化的功能。

在flask中,在执行app.run()之后,如果有请求来,会执行app.__call__方法
通过中间件的方法可以在请求来时之前与来临之后,即执行app.__call__前后执行其他代码,进行一些生命周期的控制
1
2
  • 当一个请求刚进来时: 1).执行app.call方法 2).然后调用app.wsgi_app方法
  • 如上,重新定义了一个Middleware类,而实际上返回的就是原来的wsgi_app,但是此时我们就可以在新定义的类中,定制/扩展某些动作;如print操作
  • 另外,新定义的Middleware类的call方法的参数,其实就是environ, start_response这两个参数(原来wsgi_app)的参数
  • 由于在wsgi_app这一步,我们拿到的仅有原生的environ,因此我们做的只能是对原生的environ进行操作;request、session这些都不能导出/操作(因为只有执行app.wsgi_app之后才有这些参数、方法)
  • *因为我们在中间减重不能利用请求和响应来做一些事情,所以中间件的应用场景不多;但是当我们相对原生environ做操作时,就可以用中间件了;所以一般会采用before_request等方法
from flask import Flask
app = Flask(__name__)
app.secret_key = 'asdfasdfasdf'

@app.route('/x2', methods=['GET', 'POST'])
def index():
    return "x2"

class Middleware(object): # 2、
    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)  # 还是原来的wsgi方法,我们可以在这前后做一些操作,比如ip黑名单过滤(拿到environ)。! 不能用这些,因为是在wsgi_app返回会才有的request、session
        print('after')
        return obj

if __name__ == '__main__':
    app.wsgi_app = Middleware(app.wsgi_app)  # 1、
    app.run()
    """
    1.执行app.__call__
    2.在调用app.wsgi_app方法
    """
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 11、蓝图(django的路由分发)

规范的分发路由,具体看示例

蓝图用于为应用提供目录划分:

小型应用程序:示例 (opens new window)

<https://files.cnblogs.com/files/wupeiqi/pro_flask_简单应用程序目录示例.zip>
1

大型应用程序:示例 (opens new window)

<https://files.cnblogs.com/files/wupeiqi/pro_flask_大型应用目录示例.zip>
1

其他:

  • 蓝图URL前缀:xxx = Blueprint('account', name,url_prefix='/xxx')
  • 蓝图子域名:xxx = Blueprint('account', name,subdomain='admin')

前提需要给配置SERVER_NAME: app.config['SERVER_NAME'] = 'wupeiqi.com:5000 (opens new window)'

访问时:admin.wupeiqi.com:5000/login.html (opens new window)

# 12、补充

# 1.生成项目依赖的方式

方式一:

pip3 install pipregs

- 生成依赖文件:pipregs ./   # 执行会会在根目录生成一个requirement.txt文件
- 安装依赖文件  pip instlal -r requirement.txt
1
2
3
4

方式二:

生成依赖文件:pip freeze > requirements.txt
安装依赖文件:pip instlal -r requirements.txt
1
2

# 13、函数/方法

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))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
编辑 (opens new window)
排序
flask基础(2)

← 排序 flask基础(2)→

最近更新
01
配置yun源
05-24
02
linux-配置python虚拟环境
05-24
03
linux文件目录管理
05-24
更多文章>
Theme by Vdoing | Copyright © 2023-2023 yizhang | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式