flask学习三之session和路由

Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪

  1. Flask 中 session 是需要 secret_key 的
from flask import session
app = Flask(__name__)
app.secret_key = "DragonFire"

secret_key 实际上是用来加密字符串的,如果在实例化的app中没有 secret_key 那么开启session一定会抛异常的
session["user"] = "ass"
这样用就代表这个请求带上来的session中保存了一个user='ass'
2. cookies 中的 session 是什么
cookies 中 session 存储的是通过 secret_key 加密后的 key , 通过这个 key 从flask程序的内存中找到用户对应的session信息
3. 怎么用 session 进行验证呢?
session.get("user")
4. 获取session信息:
session['user]

Flask中的路由系统其实我们并不陌生了,从一开始到现在都一直在应用

@app.route("/",methods=["GET","POST"])

  1. @app.route() 装饰器中的参数
    methods : 当前 url 地址,允许访问的请求方式
@app.route("/info", methods=["GET", "POST"])
def student_info():
    stu_id = int(request.args["id"])
    return f"Hello Old boy {stu_id}"  # Python3.6的新特性 f"{变量名}"

endpoint : 反向url地址,默认为视图函数名 (url_for)

from flask import url_for

@app.route("/info", methods=["GET", "POST"], endpoint="r_info")
def student_info():
    print(url_for("r_info"))  # /info
    # 或者 url_for("student_info")
    stu_id = int(request.args["id"])
    return f"Hello Old boy {stu_id}"  # Python3.6的新特性 f"{变量名}"

defaults : 视图函数的参数默认值{"nid":1}

from flask import url_for


@app.route("/info", methods=["GET", "POST"], endpoint="r_info", defaults={"nid": 100})
def student_info(nid):
    print(url_for("r_info"))  # /info
    # stu_id = int(request.args["id"])
    print(nid)  # 100
    return f"Hello Old boy {nid}"  # Python3.6的新特性 f"{变量名}"

strict_slashes : url地址结尾符"/"的控制 False : 无论结尾 "/" 是否存在均可以访问 , True : 结尾必须不能是 "/",不写默认为True

# 访问地址 : /info 
@app.route("/info", strict_slashes=True)
def student_info():
    return "Hello Old boy info"


# 访问地址 : /infos  or  /infos/
@app.route("/infos", strict_slashes=False)
def student_infos():
    return "Hello Old boy infos"

redirect_to : url地址重定向

# 访问地址 : /info 浏览器跳转至 /infos
@app.route("/info", strict_slashes=True, redirect_to="/infos")
def student_info():
    return "Hello Old boy info"

@app.route("/infos", strict_slashes=False)
def student_infos():
    return "Hello Old boy infos"

subdomain : 子域名前缀
subdomian="DragonFire" 这样写可以得到 DragonFire.hello.com 前提是app.config["SERVER_NAME"] = "hello.com"
在启动服务前,还需要配置DNS解析

  • DNS解析,即在访问一个网址时,会将网址映射到一个对应的IP地址上,所以我们 要在本地测试我们的admin.test.com:5000也需要配置我们的DNS解析
  • 以管理员的身份打开C:\Windows\System32\drivers\etc下面的hosts文件,在最后加入我们希望映射的网址即可
app.config["SERVER_NAME"] = "oldboy.com:5000"

@app.route("/info",subdomain="DragonFire")
def student_info():
    return "Hello Old boy info"

# 访问地址为:  DragonFire.oldboy.com:5000/info

2.动态参数路由:

from flask import url_for


# 访问地址 : http://127.0.0.1:5000/info/1
@app.route("/info/<int:nid>", methods=["GET", "POST"], endpoint="r_info")
def student_info(nid):
    print(url_for("r_info",nid=2))  # /info/2
    return f"Hello Old boy {nid}"  # Python3.6的新特性 f"{变量名}"

int:nid 就是在url后定义一个参数接收
但是这种动态参数路由,在url_for的时候,一定要将动态参数名+参数值添加进去,否则会抛出参数错误的异常

any: 可以指定多种路径,如下面的例子
url_path的变量名是自己定义的

@app.route('/<any(student,class):url_path>/<id>/')
def item(url_path, id):
    if url_path == 'student':
        return '学生{}详情'.format(id)
    else:
        return '班级{}详情'.format(id)

3.路由正则:
一般不用,如果有特殊需求,不怕麻烦的话,这个东西还是挺好用的,前提是你的正则玩儿的很6
我们可以通过继承werkzeug.routing 的BaseConverter类从而自己定义一个动态路由过滤器的规则

from flask import Flask,request
from werkzeug.routing import BaseConverter


app = Flask(__name__)
app.debug =True

class TelephoneConverter(BaseConverter):
    regex = '1[3857]\d{9}'


app.url_map.converters['tel'] = TelephoneConverter

@app.route('/student/<tel:telenum>/')
def student_detail(telenum):

    return '学生的手机号码是{}'.format(telenum)

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

注意:
1.自定义动态路由过滤器类,该类必须继承werkzeug.routing 的BaseConverter类
2.通过regex属性指定路由规则
3.将自定义的类映射到app.url_map.converters中(其本质是一个字典)
app.url_map.converters['tel'] = TelephoneConverter

自定义动态路由过滤器

自定义一个类,该通过继承werkzeug.routing 的BaseConverter类不光可以实现正则匹配,介绍以下两个方法:

  • 在该类中实现 to_python 方法:
    这个方法的返回值,将会传递给视图函数的形参。我们可以利用这个方法实现处理url中动态路由部分。
  • 在该类中实现 to_url 方法:
    翻转url的时候也就是使用url_for函数的时候,我们传入指定的动态路由部分,触发to_url方法,这个方法的返回值,会拼接在非动态路由上,从而实现生成符合要求的url格式。
from flask import Flask,request,url_for
from werkzeug.routing import BaseConverter

app = Flask(__name__)
app.debug =True


class ListConverter(BaseConverter):
    regex = '.*'     # 这个regex代表都匹配的意思,可以根据自己的需求制定url规则
    def to_python(self, value):
        '''这个函数用于拿到了路由里的动态参数赋值给value,
          可以在to_python进行操作动态参数,
          返回操作完的的结果给视图函数的形参'''
        return value.split('+')

    def to_url(self, value):
        '''这个函数用于和url_for连用,
           url_for通过指定给动态参数(以关键字实参的形式)赋值给value
           我们可以根据我们的需求操作url_for传进来的参数,
           然后返回一个理想的动态路由内容拼接在url上'''
        return '+'.join(value)


app.url_map.converters['list'] = ListConverter

@app.route('/student_list/<list:students>/')
def student_list(students):
    print(url_for('student_list',students=['a','b'])) # 输出 /student_list/a+b/

    return '{}'.format(students)


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

在平时的开发的过程中,很多需要权限验证的功能需要用到装饰器,下面的代码是如何在flask中实现一个装饰器。

from flask import Flask, request
from functools import  wraps

app = Flask(__name__)

def login_verify(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        user_name = request.args.get('user')
        password = request.args.get('password')
        if user_name == 'mark' and password == '123':
            return func(*args,**kwargs)
        else:
            return '请登录'
    return wrapper

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/my_info/')
@login_verify
def my_info():
    return '个人信息页面'

视图类的写法

class CBVTest(views.MethodView):

    methods = ['GET','POST']  # 指定可以接收的方法有什么
    decorators = [login_verify,]  # 指定自定义的装饰器

    def get(self):
        print(url_for('end_demo'))
        return 'cbv_get'
    def post(self):
        return 'cbv_post'
# 通过add_url_rule添加类视图和url的映射,并且在as_view方法中指定该url的名称,方便url_for函数调用
app.add_url_rule('/cbvtest/',view_func=CBVTest.as_view('cbvtest'))
posted @ 2020-07-17 16:34  小渣猫  阅读(199)  评论(0)    收藏  举报