开发进阶Flask的根基,知识整理

By admin in 4858.com on 2019年4月14日

 一、概述

最大的表征:短小精悍、可进展强的3个Web框架。注意点:上下文物管理理机制,依赖wsgi:werkzurg
模块

知识回想

知识点回看

Flask火速入门,知识整理,flask急忙入门整理

2、前奏学习werkzurg

先来回想二个知识点:1个类加括号会执行__init__主意,一个对象加括号执行__call__方法

事例1:

from werkzeug.wrappers import Request, Response

@Request.application
def hello(request):
    return Response('Hello World!')

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, hello)

#封装了请求和相应的对象

flask正是基于上边一步一步搭建起来的!

 

三、学习flask

第一个flask:

from flask import Flask

duo=Flask(__name__)

duo.run()   

三行  运行了程序,但是访问url,发现是Not  Found  !!!

哪些原因呢?按理说访问url,执行函数,重回结果,大家发现我们访问了,不过从未收取,在django应该怎么写,写个路由写个视图,在那也是如出一辙

from flask import Flask

duo=Flask(__name__)

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

duo.run()  

#这下执行就访问成功

其1duo.run
正是开行socket,这些剧本要以主函数去运作的时候,选用实行duo.run,外人如果导入的时候,run是不应该执行的:

from flask import Flask

duo=Flask(__name__)

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

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

1个flasl完结简单的记名:

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

duo=Flask(__name__)
duo.secret_key='shuai'   #加密方式

@duo.route('/login',methods=['GET','POST'])    #默认GET 别的请求还要添加
def login():

    if request.method == 'GET':
        #return 'Login'   #HttpResponse  django    返回字符串
        return render_template('login.html')
    #request.form ----------》#request.POST
    #request.args ----------》 #request.GET
    user=request.form.get('user')
    pwd=request.form.get('pwd')
    if user=='duoduo' and pwd =='123':
        session['user']=user
        return redirect('/index')
    return render_template('login.html',error='用户名或密码错误')

@duo.route('/index')
def index():
    user=session.get('user')
    if not user:
        return redirect('login')
    return render_template('index.html')


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

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
    <h1>用户登入</h1>
    <form method="post">
        <input type="text" name="user">
        <input type="password" name="pwd">
        <input type="submit" value="提交">{{error}}
    </form>

</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
    <h1>欢迎使用</h1>
    <img src="/static/111.jpg" alt="4858.com 1">   #图片自己找个
</body>
</html>

1、django 和flask区别?

1、flask依赖wsgi,实现wsgi的模块:wsgiref,werkzeug,uwsgi

1、Flask介绍(轻量级的框架,相当高效的就能把程序搭建起来)

  Flask是二个基于Python开发并且依赖jinja②模板和Werkzeug
WSGI服务的八个小型框架,对于Werkzeug本质是Socket服务端,其用来吸收接纳http请求并对请求举办预处理,然后触发Flask框架,开发职员基于Flask框架提供的效劳对请求进行对应的处理,并再次回到给用户,假诺要回来给用户复杂的剧情时,需求借助jinja二模板来贯彻对模板的处理,即:将模板和多少举办渲染,将渲染后的字符串再次来到给用户浏览器。

“微”(micro) 并不表示您供给把全体 Web 应用塞进单个 Python
文件(纵然真正能够 ),也不意味着 Flask
在功用上拥有欠缺。微框架中的“微”意味着 Flask
目的在于维持大旨不难而不难扩张。Flask
不会替你做出太多决策——比如利用何种数据库。而这多少个 Flask
所挑选的——比如采取何种模板引擎——则很不难替换。除了那几个之外的整整都由可由你控制。如此,Flask
能够与你相反相成。

默许情形下,Flask
不含有数据库抽象层、表单验证,或是其余任何已有多种库能够胜任的功力。不过,Flask
援救用扩张来给使用添加那么些效应,就好像是 Flask
本人完毕的一致。众多的扩张提供了数据库集成、表单验证、上传处理、各个种种的盛开认证技术等成效。Flask
恐怕是“微小”的,但它已常备不懈幸好要求繁杂的生产条件中投入使用。

pip3 install flask

 

#Flask依赖一个实现wsgi协议的模块:werkzeug
from werkzeug.wrappers import Request, Response

@Request.application
def hello(request):
    return Response('Hello World!')

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, hello)

flask依赖wsgi,实现wsgi模块:wsgiref,werkzeug,uwsgi

 

三、Flask

  最大的两样就是django请求相关的数目,通过参数二个三个传递过去的,而flask正是先把位于有个别地方,然后去取,那么些东西叫上下文物管理理

二、实例化Flask对象,里面是有参数的

与Django的简便相比较

    Django:无socket,依赖第三方模块wsgi,中间件,路由系统(CBV,FBV),视图函数,ORM。cookie,session,Admin,Form,缓存,信号,序列化。。
    Flask:无socket,中间件(需要扩展),路由系统,视图(CBV)、第三方模块(依赖jinja2),cookie,session弱爆了

 

1、简介

壹、配置文件                                                             
                             

    模块+静态文件         Flask(__name__,…) 

二、路由系统     装饰器完成的

    @duo.route(‘/index’,methods=[‘GET’])

3、视图             也有fbv,cbv

四、请求相关      导入就能用,django 而是参数

request.form 

request.args

request.method

5、响应

字符串‘’

render

redirect

六、模块渲染

7、session

session[‘xxx’]=123

session.get(‘xxx’)

8、fiash   (闪现)

九、中间件     基本不用  请求前的操作

拾、特殊的装饰器

 

借使2个setting.py:

class Foo:
    DEBUG=True
    TEST=True

二个脚本duoduo.py

path='setting.Foo'

大家怎么在path少校Foo那几个类找到?怎么着得到当中山大学写的静态字段的值:

4858.com 24858.com 3

import importlib

path='setting.Foo'

p,c=path.rsplit('.',maxsplit=1)


m=importlib.import_module(p)

cls=getattr(m,c)

for key in dir(cls):
    if key.isupper():
        print(key,getattr(cls,key))

#其实这就是配置文件导入原理

答案

2、什么是wsgi?

app = Flask(__name__,template_folder='templates',static_url_path='/xxxxxx')

二、基本使用

from flask import Flask
app = Flask(__name__)

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

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

 

2、详解

1、配置文件

flask的布置文件在哪儿吗?这个都以暗许的配置文件,

from flask import Flask

duo=Flask(__name__)

print(duo.config)

#<Config {'ENV': 'production', 'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None, 
'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': None, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 
'USE_X_SENDFILE': False, 'SERVER_NAME': None, 'APPLICATION_ROOT': '/', 'SESSION_COOKIE_NAME': 'session', 
'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 
'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_SAMESITE': None, 'SESSION_REFRESH_EACH_REQUEST': True,
'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'TRAP_BAD_REQUEST_ERRORS': None,
'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True,
'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': False, 'JSONIFY_MIMETYPE': 'application/json',
'TEMPLATES_AUTO_RELOAD': None, 'MAX_COOKIE_SIZE': 4093}>

安排文件是能够修改的,那在何地改?我们那有诸如此类两个语法:

duo.config.from_object('setting.Foo')  #还是上面的setting.py文件

咱俩来看看.from_object 中的源码:

4858.com 4

 

4858.com 5

 

 4858.com 6

我们现在的陈设文件,能够扭转不雷同的类,开发条件二个类,线上环境2个类,相同的静态属性三个类,大家依据具体的条件只需改三个类名字就能够了

 

贰、路由系统

@duo.route(url,methods(允许请求的措施),endpoint(值))

-endpoint 
 ,反向生成U劲客L,即便未有endpoint设定的值,那么暗中同意的那正是函数名

-url_for(‘endpoint设定的值’)

from flask import Flask,url_for

duo=Flask(__name__)

# print(duo.config)
duo.config.from_object('setting.Foo')
# print(duo.config)



@duo.route('/index/',methods=['GET','POST'])   #endpoint就是django反向生成的name,如果不写endpoint,url_for后面的值就是函数名
def index():
    print(url_for('index'))   #反向生成url
    return "hello world"

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

 我们在django中有的时候url会带上对象的nid值,这些在flask中是何等的格式呢?

  • @duo.route(‘/user/<username>’)      字符串
  • @duo.route(‘/post/<int:post_id>’)      整数
  • @duo.route(‘/post/<float:post_id>’)    浮点
  • @duo.route(‘/post/<path:path>’)       路径
  • @duo.route(‘/login’, methods=[‘GET’, ‘POST’])

而是默许是不扶助正则!   

那正是动态的路由

from flask import Flask,url_for

duo=Flask(__name__)

# print(duo.config)
duo.config.from_object('setting.Foo')
# print(duo.config)

@duo.route('/index/<int:nid>',methods=['GET','POST'])   #int是用来约束在url的值
def index(nid):
    print(nid)
    print(url_for('index',nid=1))     #有参数要加参数
    return "hello world"

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

 

3、FBV(CBV前边再介绍)

四、请求相关,响应相关

from flask import Flask,jsonify,make_response

duo=Flask(__name__)
@duo.route('/index/<int:nid>',methods=['GET','POST'])   #int是用来约束在url的值
def index(nid):
    # 请求相关信息
    # request.method
    # request.args
    # request.form
    # request.values
    # request.cookies
    # request.headers
    # request.path
    # request.full_path
    # request.script_root
    # request.url
    # request.base_url
    # request.url_root
    # request.host_url
    # request.host
    # request.files
    # obj = request.files['the_file_name']
    # obj.save('/var/www/uploads/' + secure_filename(f.filename))


    # 响应相关信息
    # return "字符串"
    # return render_template('html模板路径',**{})
    # return redirect('/index.html')
    # return jsonify({'k1':'v1'})    #jsonify帮你序列化
    obj=make_response('Index')    #把返回给用户的字符串,封装到这个对象    
    obj.headers['duoduo']=666   #设置响应头
    return obj
if __name__ == '__main__':
    duo.run()

运行后:

4858.com 7

陆、模板的渲染

3个登入验证,可以导入before_request,未有重返值正是足以因此,有再次来到值就不或许透过

from flask import Flask,request,before_request,session

duo=Flask(__name__)

@duo.before_request
def xxxxx():
    if request.path =='/login':  #只有登入视图可以访问
        return None
    if session.get('user') :
        return None

    return redirect('login')  #  上面不通过,返回登入页面

-基本数据类型:能够执行python的语法,如:dict.get() list[‘xx’]

-传入函数

django,自动执行

flask,不自动执行

-全局定义函数

@duo.template_global()

@duo.template_filter()

-模板的接续

{%extends ‘给谁’%}

{%block content%}

{% endblock%}

-include  直接加页面

-安全方式体现

前端:{{obj|safe}}

后端:Markup(‘obj’)

 

7、session 

session在视图中能够字典来使用,为啥能作为字典,大家来看一下源码:

from flask.sessions import SecureCookieSession

4858.com 8

 继承了dict,不用多说怎么

4858.com 9

当呼吁刚进来时:flask读取cookie中session对应的值:将以此值解密并反连串化成字典,放入内部存款和储蓄器,以便视图函数使用,

当呼吁结束时:flask会读取内部存款和储蓄器中字典的值,在举办类别化+加密,写入到用户的cookie中。(那正是session的编写制定)

 session的安顿是足以改的,关于session有以下几点:

 'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),     #生命周期
'SESSION_COOKIE_NAME':                  'session'  #名称
'SESSION_COOKIE_DOMAIN':                None    #域名
'SESSION_COOKIE_PATH':                     None       #路径
‘SESSION_COOKIE_HTTPONLY':             True    #支持HP读取
'SESSION_COOKIE_SECURE':                False  #安全性
'SESSION_REFRESH_EACH_REQUEST':   True    #最后一次访问的时间保持

8、flash

在session中储存一会数码,读取时经过pop将数据移除,以此来创立2个效果,只存叁遍,只可以取一回

实例:

from flask import Flask,flash,get_flashed_messages

duo=Flask(__name__)
duo.secret_key='duoduo'   #这是一个容易忘记的点
#出现secret_key 的报错就是这个设置

@duo.route('/page1')
def page1():
    flash('大娃','boy')   
    flash('二娃','boy')
    flash('蛇精','girl')
    return 'session'

@duo.route('/page2')
def page2():
    print(get_flashed_messages(category_filter=['boy']))

    return 'session'

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

走访一下,取一下,大家来探视源码:

4858.com 10

 

4858.com 11

 

 9、中间件

那大家先来打听一下flask是怎么运作起来的:

先写贰个简易的本子:

from flask import Flask
duo=Flask(__name__)

@duo.route('/index')
def index():
    print('index')
    return 'Index'

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

率先,先点开源码的duo.run:

  4858.com 12

run的self正是flask的对象,请求进入第3给参数前边加括号,是还是不是flask的靶子加括号,正是调用,对象调用执行__call__方法:

duo.__call__  #进去看看

4858.com 13

当上边包车型地铁台本运转,只有请求访问,才实施__call__方法

三个粗略的使用

from flask import Flask

duo=Flask(__name__)

@duo.route('/index')
def index():
    print('index')
    return 'Index'

class Middleware(object):
    def __init__(self,old):
        self.old=old

    def __call__(self, *args, **kwargs):
        print('执行前')
        ret=self.old(*args,**kwargs)
        print('执行后')
        return ret

if __name__ == '__main__':
    duo.wsgi_app=Middleware(duo.wsgi_app)   
    duo.run()

 

10、特殊的装饰器(重点)

before_request   #何人先定义执行

after_request   #从后往上推行

这地方四个原理正是把函数名放到二个列表,然后循环的体制

from flask import Flask

duo=Flask(__name__)


@duo.before_request
def x1():
    print('before')

@duo.after_request
def x2(reponse):    #这里必须要有返回值
    print('after')
    return reponse

@duo.route('/index1')
def index1():
    print('index')
    return 'Index'

@duo.route('/order')
def order():
    print('order')
    return 'order'

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

那边有二个留意点就是,before_request有重临值的话,要走富有的after_request
,在django一.玖从前都只是这么些流程,后来改了编写制定,

咱俩发现1.10过后,走最外侧6在那之中间件就回来。

 

before_first_开发进阶Flask的根基,知识整理。request      #只进行运行起来
第三遍,后就不再实施,前面详细看源码

template_global    #  渲染 全局定义函数

template_filter     #   不一致的全局定义函数

 errorhandler   #定制错误音讯

@duo.errorhandler(404)
def not_found(arg):
    print(arg)
    return '没找到'    #定制错误信息的页面比较常用

 

  web服务网关接口,wsgi就是三个斟酌和专业,实现该协议的模块:

三、三种添加路由的艺术

 1.实例化Flask对象时,可选的参数

template_folder:模板所在文书夹的名字

root_path:能够不用填,会自行找到,当前实施文书,所在目录地址

在return render_template时会将地点四个进行拼接,找到呼应的模板地址

static_folder:静态文件所在文件的名字,暗中认可是static,能够不用填

static_url_path:静态文件的地点前缀,写成什么,访问静态文件时,就要在前头加上这几个

app = Flask(__name__,template_folder='templates',static_url_path='/xxxxxx')

 

如:在根目录下创办目录,templates和static,则return
render_template时,能够找到里面包车型地铁模版页面;如在static文件夹里存放1一.png,在引用该图形时,静态文件地点为:/xxxxxx/1一.png

 

#方式一
    @app.route('/index.html',methods=['GET','POST'],endpoint='index')
    def index():
        return 'Index'

#方式二

def index():
    return "Index"

self.add_url_rule(rule='/index.html', endpoint="index", view_func=index, methods=["GET","POST"])    #endpoint是别名
or
app.add_url_rule(rule='/index.html', endpoint="index", view_func=index, methods=["GET","POST"])
app.view_functions['index'] = index

 

添加路由关系的精神:将url和视图函数封装成三个Rule对象,添加到Flask的url_map字段中

 

  -wsgiref

方式一:
  @app.route('/xxxx')  # @decorator
  def index():
     return "Index"
方式二:
  def index():
     return "Index"
  app.add_url_rule('/xxx', "n1", index)  #n1是别名 

二.Flask中装饰器应用

from flask import Flask,render_template,request,redirect,session
app = Flask(__name__)
app.secret_key = "sdsfdsgdfgdfgfh"   # 设置session时,必须要加盐,否则报错

def wrapper(func):
    def inner(*args,**kwargs):
        if not session.get("user_info"):
            return redirect("/login")
        ret = func(*args,**kwargs)
        return ret
    return inner

@app.route("/login",methods=["GET","POST"])  # 指定该路由可接收的请求方式,默认为GET
def login():
    if request.method=="GET":
        return render_template("login.html")
    else:
        # print(request.values)   #这个里面什么都有,相当于body
        username = request.form.get("username")
        password = request.form.get("password")
        if username=="haiyan" and password=="123":
            session["user_info"] = username
            # session.pop("user_info")  #删除session
            return redirect("/index")
        else:
            # return render_template("login.html",**{"msg":"用户名或密码错误"})
            return render_template("login.html",msg="用户名或者密码错误")

@app.route("/index",methods=["GET","POST"])
@wrapper    #自己定义装饰器时,必须放在路由的装饰器下面
def index():
    # if not session.get("user_info"):
    #     return redirect("/login")
    return render_template("index.html")


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

 

debug = True 是指进入调节和测试格局,服务器会在 大家的代码修改后,
自动重新载入,有不当的话会提示,每一回修改代码后就不必要再手动重启

点击查看详情

 

  -werkzeug

四、添加路由关系的原形

四.伸手响应相关

  达成其情商的模块本质上正是socket服务端用于收纳用户请求,并处理,

  将url和视图函数封装成1个Rule对象)添加到Flask的url_map字段中

1.获得请求数据,及相应

    - request
            - request.form   #POST请求的数据
            - request.args   #GET请求的数据,不是完全意义上的字典,通过.to_dict可以转换成字典
            - request.querystring  #GET请求,bytes形式的
        - response
            - return render_tempalte()    
            - return redirect()
            - return ""
            v = make_response(返回值)  #可以把返回的值包在了这个函数里面,然后再通过.set_cookie绑定cookie等
        - session
            - 存在浏览器上,并且是加密的
            - 依赖于:secret_key

  一般web框架基于wsgi实现,那样完结关切点分离(通俗的说工作相关的,交给框架)

伍、Flask中装饰器应用

二.flask中收获UPAJEROL后边的参数(from urllib.parse import urlencode,quote,unquote)

GET请求:

URL为: 

 

from urllib.parse import urlencode,quote,unquote

def login():
    if request.method == 'GET':
        s1 = request.args
        s2 = request.args.to_dict()
        s3 = urlencode(s1)
        s4 = urlencode(s2)
        s5 = unquote(s3)
        s6 = unquote(s4)
        s7 = quote("胡冲")
        print('s1',s1)
        print('s2',s2)
        print('s3',s3)
        print('s4',s4)
        print('s5',s5)
        print('s6',s6)
        print('s7',s7)

        return render_template('login.html')

#############结果如下####################

s1 ImmutableMultiDict([('name', "'胡冲'"), ('nid', '2')])
s2 {'name': "'胡冲'", 'nid': '2'}
s3 name=%27%E8%83%A1%E5%86%B2%27&nid=2
s4 name=%27%E8%83%A1%E5%86%B2%27&nid=2
s5 name='胡冲'&nid=2
s6 name='胡冲'&nid=2
s7 %E8%83%A1%E5%86%B2

 

from werkzeug.wrappers import  Responsefrom werkzeug.serving import run_simpledef run_sever(environ,start_response):    response=Response('duoduo')   # 封装一下    return response(environ,start_response)if __name__ == '__main__':    run_simple('127.0.0.1',8000,run_sever)
from flask import Flask,render_template,request,redirect,session
app = Flask(__name__)
app.secret_key = "sdsfdsgdfgdfgfh"

def wrapper(func):
    def inner(*args,**kwargs):
        if not session.get("user_info"):
            return redirect("/login")
        ret = func(*args,**kwargs)
        return ret
    return inner

@app.route("/login",methods=["GET","POST"])
def login():
    if request.method=="GET":
        return render_template("login.html")
    else:
        # print(request.values)   #这个里面什么都有,相当于body
        username = request.form.get("username")
        password = request.form.get("password")
        if username=="haiyan" and password=="123":
            session["user_info"] = username
            # session.pop("user_info")  #删除session
            return redirect("/index")
        else:
            # return render_template("login.html",**{"msg":"用户名或密码错误"})
            return render_template("login.html",msg="用户名或者密码错误")

@app.route("/index",methods=["GET","POST"])
@wrapper
def index():
    # if not session.get("user_info"):
    #     return redirect("/login")
    return render_template("index.html")


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

叁、配置文件

 点击查看

 

+ View Code?

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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:     {         'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式         'TESTING':                              False,                          是否开启测试模式         'PROPAGATE_EXCEPTIONS':                 None,                                   'PRESERVE_CONTEXT_ON_EXCEPTION':        None,         'SECRET_KEY':                           None,         'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),         'USE_X_SENDFILE':                       False,         'LOGGER_NAME':                          None,         'LOGGER_HANDLER_POLICY':               'always',         'SERVER_NAME':                          None,         'APPLICATION_ROOT':                     None,         'SESSION_COOKIE_NAME':                  'session',         'SESSION_COOKIE_DOMAIN':                None,         'SESSION_COOKIE_PATH':                  None,         'SESSION_COOKIE_HTTPONLY':              True,         'SESSION_COOKIE_SECURE':                False,         'SESSION_REFRESH_EACH_REQUEST':         True,         'MAX_CONTENT_LENGTH':                   None,         'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),         'TRAP_BAD_REQUEST_ERRORS':              False,         'TRAP_HTTP_EXCEPTIONS':                 False,         'EXPLAIN_TEMPLATE_LOADING':             False,         'PREFERRED_URL_SCHEME':                 'http',         'JSON_AS_ASCII':                        True,         'JSON_SORT_KEYS':                       True,         'JSONIFY_PRETTYPRINT_REGULAR':          True,         'JSONIFY_MIMETYPE':                     'application/json',         'TEMPLATES_AUTO_RELOAD':                None,     }   方式一:     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://[email protected]/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目录

 

三、flask提供的功能

伍、请求响应相关

 肆、路由系统

配置文件

    - request
            - request.form   #POST请求
            - request.args   #GET请求  字典形式的
            - request.querystring  #GET请求,bytes形式的
        - response
            - return render_tempalte()
            - return redirect()
            - return ""
            v = make_response(返回值)  #吧返回的值包在了这个函数里面
        - session
            - 存在浏览器上,并且是加密的
            - 依赖于:secret_key

 1.可传唱参数:

@app.route('/user/<username>')   #常用的   不加参数的时候默认是字符串形式的
@app.route('/post/<int:post_id>')  #常用的   #指定int,说明是整型的
@app.route('/post/<float:post_id>')
@app.route('/post/<path:path>')
@app.route('/login', methods=['GET', 'POST'])

 

?

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

 

 

  全体配置文件都在flask的对象.config中

flask配置文件

二.反向生成UCRUISERL: url_for

endpoint(“name”)   #别名,相当于django中的name

 

from flask import Flask, url_for

@app.route('/index',endpoint="xxx")  #endpoint是别名
def index():
    v = url_for("xxx")
    print(v)
    return "index"

@app.route('/zzz/<int:nid>',endpoint="aaa")  #endpoint是别名
def zzz(nid):
    v = url_for("aaa",nid=nid)
    print(v)
    return "index2"

 

  flask的对象.config.from_object 小写也是卓有成效的

4858.com 144858.com 15

3.  @app.route和app.add_url_rule参数

@app.route和app.add_url_rule参数:
            rule,                       URL规则
            view_func,                  视图函数名称
            defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
            endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
            methods=None,               允许的请求方式,如:["GET","POST"]


            strict_slashes=None,        对URL最后的 / 符号是否严格要求,
                                        如:
                                            @app.route('/index',strict_slashes=False), #当为False时,url上加不加斜杠都行
                                                访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可
                                            @app.route('/index',strict_slashes=True)  #当为True时,url后面必须不加斜杠
                                                仅访问 http://www.xx.com/index 
            redirect_to=None,           由原地址直接重定向到指定地址,原url有参数时,跳转到的新url也得传参,注意:新url中不用指定参数类型,直接用旧的参数的类型
                                        如:
                                            @app.route('/index/<int:nid>', redirect_to='/home/<nid>') # 访问index时,会直接自动跳转到home,执行home的函数,

                                                            不执行index的

                          或
                                            def func(adapter, nid):
                                                return "/home/888"
                                            @app.route('/index/<int:nid>', redirect_to=func)

            subdomain=None,             子域名访问
                                                from flask import Flask, views, url_for

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


                                                @app.route("/", subdomain="admin")
                                                def static_index():
                                                    """Flask supports static subdomains
                                                    This is available at static.your-domain.tld"""
                                                    return "admin.xxx.com"

                            #动态生成
                                                @app.route("/dynamic", subdomain="<username>")
                                                def username_index(username):
                                                    """Dynamic subdomains are also supported
                                                    Try going to user1.your-domain.tld/dynamic"""
                                                    return username + ".your-domain.tld"


                                                if __name__ == '__main__':
                                                    app.run()
        所有的域名都得与IP做一个域名解析:
        如果你想通过域名去访问,有两种解决方式:
          方式一:
            1、租一个域名   haiyan.lalala
            2、租一个公网IP  49.8.5.62
            3、域名解析:
                           haiyan.com    49.8.5.62
            4、吧代码放在49.8.5.62这个服务器上,程序运行起来
              用户可以通过IP进行访问
          方式二:如果是自己测试用的就可以用这种方式。先在自己本地的文件中找
             C:\Windows\System32\drivers\etc  找到HOST,修改配置
            然后吧域名修改成自己的本地服务器127.0.0.1
            加上配置:app.config["SERVER_NAME"] = "haiyan.com:5000"

 

# =============== 子域名访问============
@app.route("/static_index", subdomain="admin")
def static_index():
    return "admin.bjg.com"

# ===========动态生成子域名===========
@app.route("/index",subdomain='<xxxxx>')
def index(xxxxx):
    return "%s.bjg.com" %(xxxxx,)

 

  应用: importlib 、getattr

 1 flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
 2     {
 3         'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
 4         'TESTING':                              False,                          是否开启测试模式
 5         'PROPAGATE_EXCEPTIONS':                 None,                          
 6         'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
 7         'SECRET_KEY':                           None,
 8         'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
 9         'USE_X_SENDFILE':                       False,
10         'LOGGER_NAME':                          None,
11         'LOGGER_HANDLER_POLICY':               'always',
12         'SERVER_NAME':                          None,
13         'APPLICATION_ROOT':                     None,
14         'SESSION_COOKIE_NAME':                  'session',
15         'SESSION_COOKIE_DOMAIN':                None,
16         'SESSION_COOKIE_PATH':                  None,
17         'SESSION_COOKIE_HTTPONLY':              True,
18         'SESSION_COOKIE_SECURE':                False,
19         'SESSION_REFRESH_EACH_REQUEST':         True,
20         'MAX_CONTENT_LENGTH':                   None,
21         'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
22         'TRAP_BAD_REQUEST_ERRORS':              False,
23         'TRAP_HTTP_EXCEPTIONS':                 False,
24         'EXPLAIN_TEMPLATE_LOADING':             False,
25         'PREFERRED_URL_SCHEME':                 'http',
26         'JSON_AS_ASCII':                        True,
27         'JSON_SORT_KEYS':                       True,
28         'JSONIFY_PRETTYPRINT_REGULAR':          True,
29         'JSONIFY_MIMETYPE':                     'application/json',
30         'TEMPLATES_AUTO_RELOAD':                None,
31     }
32  
33 方式一:
34     app.config['DEBUG'] = True
35  
36     PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)
37  
38 方式二:
39     app.config.from_pyfile("python文件名称")
40         如:
41             settings.py
42                 DEBUG = True
43  
44             app.config.from_pyfile("settings.py")
45  
46     app.config.from_envvar("环境变量名称")
47         环境变量的值为python文件名称名称,内部调用from_pyfile方法
48  
49  
50     app.config.from_json("json文件名称")
51         JSON文件名称,必须是json格式,因为内部会执行json.loads
52  
53     app.config.from_mapping({'DEBUG':True})
54         字典格式
55  
56     app.config.from_object("python类或类的路径")
57  
58         app.config.from_object('pro_flask.settings.TestingConfig')
59  
60         settings.py
61  
62             class Config(object):
63                 DEBUG = False
64                 TESTING = False
65                 DATABASE_URI = 'sqlite://:memory:'
66  
67             class ProductionConfig(Config):
68                 DATABASE_URI = 'mysql://user@localhost/foo'
69  
70             class DevelopmentConfig(Config):
71                 DEBUG = True
72  
73             class TestingConfig(Config):
74                 TESTING = True
75  
76         PS: 从sys.path中已经存在路径开始写
77      
78  
79     PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录

四.自定制正则路由卓殊

壮大Flask的路由系统,让她援助正则,那些类必须那样写,必须去继承BaseConverter

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 int(value)

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

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

    # 进行使用
    @app.route('/index/<regex("\d+"):nid>',endpoint='xx')
    def index(nid):
        url_for('xx',nid=123) 
        return "Index"

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

 

    django中间件

配置文件

5、视图函数

    rest framework全局配置

一、路由系统

1.Django中的CBV模式

4858.com 16

 

session

一、可传唱参数:

2.Flask中的CBV

def auth(func):
    def inner(*args, **kwargs):
        result = func(*args, **kwargs)
        return result
    return inner

class IndexView(views.MethodView):
    # methods = ['POST']  #只允许POST请求访问
    decorators = [auth,]  # 如果想给所有的get,post请求加装饰器,就可以这样来写,也可以单个指定

    def get(self):   #如果是get请求需要执行的代码
        v = url_for('index')
        print(v)
        return "GET"

    def post(self):  #如果是post请求执行的代码
        return "POST"

app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  #name即FBV中的endpoint,指别名

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

 

  加密后放置在用户浏览器的cookie中

@app.route('/user/<username>')   #常用的   不加参数的时候默认是字符串形式的
@app.route('/post/<int:post_id>')  #常用的   #指定int,说明是整型的
@app.route('/post/<float:post_id>')
@app.route('/post/<path:path>')
@app.route('/login', methods=['GET', 'POST'])

6、请求与响应

4858.com 17
from flask import Flask from flask import request from flask import
render_template from flask import redirect from flask import
make_response app = Flask(__name__) @app.route(‘/login.html’,
methods=[‘GET’, “POST”]) def login(): # 请求相关消息 #
request.method # request.args # request.form # request.values #
request.cookies # request.headers # request.path # request.full_path
# request.script_root # request.url # request.base_url #
request.url_root # request.host_url # request.host # request.files
# obj = request.files[‘the_file_name’] #
obj.save(‘/var/www/uploads/’ + secure_filename(f.filename)) #
响应相关音讯 # return “字符串” # return
render_template(‘html模板路径’,**{}) # return
redirect(‘/index.html’) # response =
make_response(render_template(‘index.html’)) #
response是flask.wrappers.Response类型 # response.delete_cookie(‘key’)
# response.set_cookie(‘key’, ‘value’) #
response.headers[‘X-Something’] = ‘A value’ # return response return
“内容” if __name__ == ‘__main__’: app.run() View Code

 

from flask import Flask,url_for,request,redirect,render_template,jsonify,make_response
from urllib.parse import urlencode,quote,unquote
app = Flask(__name__)

@app.route('/index',endpoint='xx')
def index():
    from werkzeug.datastructures import ImmutableMultiDict
  =================
    # get_data = request.args
    # get_dict = get_data.to_dict()
    # get_dict['xx'] = '18'
    # url = urlencode(get_dict)
    # print(url)
  ====================
    # print(request.query_string)
    # print(request.args)
  ==========================
    # val = "%E6%8A%8A%E5%87%A0%E4%B8%AA"
    # print(unquote(val))   #把上面这样的数据转换成中文
    #
    # return "Index"

    # return "Index"
    # return redirect()
    # return render_template()
    # return jsonify(name='alex',age='18')  #相当于JsonResponse
  =======================
    response = make_response('xxxxx')   ##如果是返回更多的值,cookie,headers,或者其他的就可用它
    response.headers['xxx'] = '123123'
    return response


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

 

  流程:

 

七、模板语法

    请求到来——–》视图函数———》请求截止

常用路由系统有上述各样,全体的路由系统都以基于一下对应涉及来拍卖:

一、模板的应用

Flask使用的是Jinja二模板,所以其语法和Django无太大差别

Flask中模板里面,执行函数时,要求带()才实施

  配置文件 生命周期3一天 加密设置

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

一.为了防止xss攻击,加了注解,所以页面上显得字符串的情势,化解办法,有三种办法

方法一:在后端使用马克up,等价于Django里的mark_safe

 

 v = Markup("<input type='text' />")

 

方法二:在前端采取safe

{{ v1|safe }}

 

 

路由

 

二、自定义模板方法

Flask中自定义模板方法的主意和Bottle相似,创立2个函数并因而参数的格局传播render_template,

run.py

from flask import Flask,url_for,render_template,Markup
app = Flask(__name__)

def test(a,b):    #自定义的标签,此方法在使用时,需要在render_temlate中传入到指定以页面使用
    return a+b

@app.template_global()   # 不需要传入,可直接在页面使用
def sb(a1, a2):
    return a1 + a2 + 100


@app.template_filter()    #不需要传入,使用时要在一个值(此值作为第一个参数传入到过滤器中)的后面加入|,然后再加参数
def db(a1, a2, a3):
    return a1 + a2 + a3

@app.route('/index')
def index():
    v1 = "字符串"
    v2 = [11,22,33]
    v3 = {"k1":"v3","sdf":"sdgfgf"}
    v4 = "<input type='text' />"
    v5 = Markup("<input type='text' />")
    return render_template("index.html",v1=v1,v2=v2,v3=v3,v4=v4,v5=v5,test=test)

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

 

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width">
    <title>Title</title>
</head>
<body>
{{ v1 }}
<ul>
    {% for foo in v2 %}
       <li>{{ foo }}</li>
    {% endfor %}
    {{ v2.1 }}

    {% for k,v in v3.items() %}
    <li>{{ k }} {{ v }}</li>
    {% endfor %}
    {{ v3.k1 }}
    {{ v3.get("k1") }}

    {{ v4|safe }}
    {{ v5 }}

    <h1>{{ test(1,2) }}</h1>
    <p>{{ sb(1,2) }}</p>
    <p>{{ 1| db(2,3) }}</p>
</ul>
</body>
</html>

 

PS:模板继承的艺术和django的等同。

 

  带参数的装饰器,自定义装饰器放下边

二、反向生成U陆风X八L: url_for

3.宏

唯有定义的东西在重重地点去行使的时候才去用它,

html

{% macro xx(name, type='text', value='') %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">

  <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
  <input type="{{ type }}" name="{{ name }}" value="{{ value }}">

{% endmacro %}

{{ xx('n1') }} 

一定于在页面上定义了四个名字为xx的’函数’,那一个函数接收一个参数,我们给type和value写上了私下认可值,此时调用,大家还亟需传入一个参数,大家这时候传到了三个n1,则

页面上会生成一个input框,name都为n一

 

  常用url,methods,endpoint 反向 url_for

endpoint(“name”)   #别名,相当于django中的name

八、Session

除请求对象之外,还有二个 session
对象。它同意你在差异请求间存款和储蓄特定用户的音信。它是在 Cookies
的功底上落成的,并且对 库克ies
进行密钥签名要利用会话,你须要安装二个密钥。

  • 设置:session[‘username’] = ‘xxx’

  • 删除:session.pop(‘username’, None)

from flask import Flask,url_for,session

app = Flask(__name__)
app.secret_key = "sdsfdgdgdgd"
app.config['SESSION_COOKIE_NAME'] = 'session_lvning'  #设置session的名字

@app.route('/index/')
def index(nid):
    #session本质上操作的是字典, 所有对session操作的方法与字典方法相同
    #session的原理:如果下一次访问的时候带着随机字符串,会把session里面对应的
    # 值拿到内存,假设session保存在数据库,每执行一次链接一次数据库,每次都要时时更新的话,会非常损耗数据库的效率
    session["xxx"] = 123
    session["xxx2"] = 123
    session["xxx3"] = 123
    session["xxx4"] = 123
    del session["xxx2"]  #在这删除了,真正存储的时候是没有xxx2的
    return "ddsf"

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

 

关于session的配置

 app.config['SESSION_COOKIE_NAME'] = 'session_lvning'

- session超时时间如何设置?      'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)
 以下是跟session相关的配置文件
"""
            'SESSION_COOKIE_NAME':                  'session',
            'SESSION_COOKIE_DOMAIN':                None,
            'SESSION_COOKIE_PATH':                  None,
            'SESSION_COOKIE_HTTPONLY':              True,
            'SESSION_COOKIE_SECURE':                False,
            'SESSION_REFRESH_EACH_REQUEST':         True,  #是否每次都跟新
            'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)

 

4858.com 18from
flask import Flask, session, redirect, url_for, escape, request app =
Flask(__name__) @app.route(‘/’) def index(): if ‘username’ in
session: return ‘Logged in as %s’ % escape(session[‘username’]) return
‘You are not logged in’ @app.route(‘/login’, methods=[‘GET’, ‘POST’])
def login(): if request.method == ‘POST’: session[‘username’] =
request.form[‘username’] return redirect(url_for(‘index’)) return ”’
<form action=”” method=”post”> <p><input type=text
name=username> <p><input type=submit value=Login>
</form> ”’ @app.route(‘/logout’) def logout(): # remove the
username from the session if it’s there session.pop(‘username’, None)
return redirect(url_for(‘index’)) # set the secret key. keep this
really secret: app.secret_key = ‘A0Zr98j/3yX R~XHH!jmN]LWX/,?猎豹CS六T’ 基本选择
4858.com 19
pip3 install Flask-Session run.py from flask import Flask from flask
import session from pro_flask.utils.session import MySessionInterface
app = Flask(__name__) app.secret_key = ‘A0Zr98j/3yX
R~XHH!jmN]LWX/,?RT’ app.session_interface = MySessionInterface()
@app.route(‘/login.html’, methods=[‘GET’, “POST”]) def login():
print(session) session[‘user1’] = ‘alex’ session[‘user2’] = ‘alex’
del session[‘user2’] return “内容” if __name__ == ‘__main__’:
app.run() session.py #!/usr/bin/env python # -*- coding:utf-8 -*-
import uuid import json from flask.sessions import SessionInterface from
flask.sessions import SessionMixin from itsdangerous import Signer,
BadSignature, want_bytes class MySession(dict, SessionMixin): def
__init__(self, initial=None, sid=None): self.sid = sid self.initial
= initial super(MySession, self).__init__(initial or ()) def
__setitem__(self, key, value): super(MySession,
self).__setitem__(key, value) def __getitem__(self, item):
return super(MySession, self).__getitem__(item) def
__delitem__(self, key): super(MySession, self).__delitem__(key)
class MySessionInterface(SessionInterface): session_class = MySession
container = {} def __init__(self): import redis self.redis =
redis.Redis() def _generate_sid(self): return str(uuid.uuid4()) def
_get_signer(self, app): if not app.secret_key: return None return
Signer(app.secret_key, salt=’flask-session’, key_derivation=’hmac’)
def open_session(self, app, request): “””
程序刚运营时执行,需求回到多少个session对象 “”” sid =
request.cookies.get(app.session_cookie_name) if not sid: sid =
self._generate_sid() return self.session_class(sid=sid) signer =
self._get_signer(app) try: sid_as_bytes = signer.unsign(sid) sid =
sid_as_bytes.decode() except BadSignature: sid =
self._generate_sid() return self.session_class(sid=sid) #
session保存在redis中 # val = self.redis.get(sid) # session保存在内部存款和储蓄器中
val = self.container.get(sid) if val is not None: try: data =
json.loads(val) return self.session_class(data, sid=sid) except: return
self.session_class(sid=sid) return self.session_class(sid=sid) def
save_session(self, app, session, response): “””
程序甘休前实施,能够保存session中拥有的值 如: 保存到resit
写入到用户cookie “”” domain = self.get_cookie_domain(app) path =
self.get_cookie_path(app) httponly = self.get_cookie_httponly(app)
secure = self.get_cookie_secure(app) expires =
self.get_expiration_time(app, session) val = json.dumps(dict(session))
# session保存在redis中 # self.redis.setex(name=session.sid, value=val,
time=app.permanent_session_lifetime) # session保存在内部存款和储蓄器中
self.container.setdefault(session.sid, val) session_id =
self._get_signer(app).sign(want_bytes(session.sid))
response.set_cookie(app.session_cookie_name, session_id,
expires=expires, httponly=httponly, domain=domain, path=path,
secure=secure) 自定义Session
4858.com 20#!/usr/bin/env
python # -*- coding:utf-8 -*- “”” pip3 install redis pip3 install
flask-session “”” from flask import Flask, session, redirect from
flask.ext.session import Session app = Flask(__name__) app.debug =
True app.secret_key = ‘asdfasdfasd’ app.config[‘SESSION_TYPE’] =
‘redis’ from redis import Redis app.config[‘SESSION_REDIS’] =
Redis(host=’192.168.0.94′,port=’6379′) Session(app) @app.route(‘/login’)
def login(): session[‘username’] = ‘alex’ return redirect(‘/index’)
@app.route(‘/index’) def index(): name = session[‘username’] return
name if __name__ == ‘__main__’: app.run() 第三方session

 

4858.com,视图

反向解析需求导入:

九、蓝图

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

微型应用程序:示例

大型应用程序:示例

其他:

  • 蓝图URL前缀:xxx = Blueprint(‘account’,
    __name__,url_prefix=’/xxx’)
  • 蓝图子域名:xxx = Blueprint(‘account’,
    __name__,subdomain=’admin’)
    # 前提须要给配备SE凯雷德VEPAJERO_NAME: app.config[‘SERVER_NAME’] =
    ‘hc.com:5000’
    # 访问时:admin.hc.com:5000/login.html

 

  FBV

from flask import Flask, url_for

@app.route('/index',endpoint="xxx")  #endpoint是别名
def index():
    v = url_for("xxx")
    print(v)
    return "index"

@app.route('/zzz/<int:nid>',endpoint="aaa")  #endpoint是别名
def zzz(nid):
    v = url_for("aaa",nid=nid)
    print(v)
    return "index2"

十、闪现(flash)

session存在在服务端的3个字典里面,session保存起来,取二遍里面大概有个别,直到你剔除之后才未有了

非同一般装饰器

3、@app.route和app.add_url_rule参数

1、本质

flash是基于session创设的,flash帮忙往里面放值,只要您取一下就从未了,也正是pop了壹晃。不仅能够得到值,而且能够把其从session里的排除,

依据Session完结的用来保存数据的集结,其性状是:使用3遍就删除。

  before_first_request

 @app.route和app.add_url_rule参数:
            rule,                       URL规则
            view_func,                  视图函数名称
            defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
            endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
            methods=None,               允许的请求方式,如:["GET","POST"]


            strict_slashes=None,        对URL最后的 / 符号是否严格要求,
                                        如:
                                            @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,           重定向到指定地址
                                        如:
                                            @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,             子域名访问
                                                from flask import Flask, views, url_for

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


                                                @app.route("/", subdomain="admin")
                                                def static_index():
                                                    """Flask supports static subdomains
                                                    This is available at static.your-domain.tld"""
                                                    return "admin.xxx.com"

                            #动态生成
                                                @app.route("/dynamic", subdomain="<username>")
                                                def username_index(username):
                                                    """Dynamic subdomains are also supported
                                                    Try going to user1.your-domain.tld/dynamic"""
                                                    return username + ".your-domain.tld"


                                                if __name__ == '__main__':
                                                    app.run()
        所有的域名都得与IP做一个域名解析:
        如果你想通过域名去访问,有两种解决方式:
          方式一:
            1、租一个域名   haiyan.lalala
            2、租一个公网IP  49.8.5.62
            3、域名解析:
                           haiyan.com    49.8.5.62

            4、吧代码放在49.8.5.62这个服务器上,程序运行起来
              用户可以通过IP进行访问

          方式二:如果是自己测试用的就可以用这种方式。先在自己本地的文件中找
             C:\Windows\System32\drivers\etc  找到HOST,修改配置
            然后吧域名修改成自己的本地服务器127.0.0.1
            加上配置:app.config["SERVER_NAME"] = "haiyan.com:5000"

 

2、闪现的用处

某些数据仅需用二回时,能够利用闪现

from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
app = Flask(__name__)
app.secret_key ='sdfsdfsdf'

@app.route('/users')
def users():
    # 方式一
    # msg = request.args.get('msg','')
    # 方式二
    # msg = session.get('msg')
    # if msg:
    #     del session['msg']
    # 方式三
    v = get_flashed_messages()  # 获取flash中的值
    print(v)
    msg = ''
    return render_template('users.html',msg=msg)

@app.route('/useradd')
def user_add():
    # 在数据库中添加一条数据
    # 假设添加成功,在跳转到列表页面时,显示添加成功
    # 方式一
    # return redirect('/users?msg=添加成功')
    # 方式二
    # session['msg'] = '添加成功'
    # 方式三
    flash('添加成功')
    return redirect('/users')


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

 

  before_request

 练习以上的参数

十一、中间件

在函数执行在此之前或函数执行之后想做点事情,有二种格局

第一种:装饰器

其次种:flask里面包车型地铁扩充,也就是django中的中间件

 

from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
app = Flask(__name__)
app.secret_key ='sdfsdfsdf'

@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('/index')
def index():
    print('index')
    return 'Index'

@app.route('/order')
def order():
    print('order')
    return 'order'

@app.route('/test')
def test():
    print('test')
    return 'test'

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

 

运营结果:

4858.com 21

还有三个@app.before_first_request:表示,当程序运维起来,第多少个请求来的时候就只举办3次,下次再来就不会在举办了

 

  after_request

redirect_to:直接重定向,原url有参数时,跳转是也得传参,注意:不用加类型

#/old
@app.route('/old/<int:nid>',redirect_to="/new/<nid>")
def old(nid):
    return "old"
# /new
@app.route('/new/<int:nid>')
def new(nid):
    return "new"

# ============对url最后的/符号是否严格要求=========
@app.route('/test',strict_slashes=True)  #当为True时,url后面必须不加斜杠
def test():
    return "aaaaaaaa"
@app.route('/test',strict_slashes=False)  #当为False时,url上加不加斜杠都行
def test():
    return "aaaaaaaa"

# =============== 子域名访问============
@app.route("/static_index", subdomain="admin")
def static_index():
    return "admin.bjg.com"

# ===========动态生成子域名===========
@app.route("/index",subdomain='<xxxxx>')
def index(xxxxx):
    return "%s.bjg.com" %(xxxxx,)

102、请求扩张

4858.com 22#!/usr/bin/env
python # -*- coding:utf-8 -*- from flask import Flask, Request,
render_template app = Flask(__name__, template_folder=’templates’)
app.debug = True @app.before_first_request #
只在率先次呼吁到来时实施叁回,前边不会再进行 def
before_first_request1(): print(‘before_first_request1’)
@app.before_first_request def before_first_request2():
print(‘before_first_request2’) @app.before_request #
每一趟请求到来时,都会执行 def before_request1(): Request.nnn = 123
print(‘before_request1’) @app.before_request def before_request2():
print(‘before_request2’) @app.after_request # 每便响应时实行 def
after_request1(response): print(‘before_request1’, response) return
response @app.after_request def after_request2(response):
print(‘before_request2’, response) return response
@app.errorhandler(404) def page_not_found(error): return ‘This page
does not exist’, 404 @app.template_global() #
自定义标签,全数页面都一向利用 def sb(a一, a二): return a① + a2@app.template_filter() # 自定义过滤器,全部页面都一向使用 def db(a一,
a2, a叁): return a一 + a二 + a三 @app.route(‘/’) #
访问的url,不加其余后缀时,也要有/ def hello_world(): return
render_template(‘hello.html’) if __name__ == ‘__main__’:
app.run() View Code

自定义标签和过滤器在页面上的调用方式:{{sb(1,2)}}  {{ 1|db(2,3)}}

 

1、Flask介绍(轻量级的框架,十分飞速的就能把程序搭建起来)
Flask是二个依据Python开发并且…

  template_global()

推而广之Flask的路由系统,让她帮衬正则,那么些类必须这么写,必须去继承BaseConverter

  template_filter()

from flask import Flask,url_for

    app = Flask(__name__)

    # 定义转换的类
    from werkzeug.routing import BaseConverter
    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中的参数
            :param value: 
            :return: 
            """
            val = super(RegexConverter, self).to_url(value)
            return val

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

    # 进行使用
    @app.route('/index/<regex("\d+"):nid>',endpoint='xx')
    def index(nid):
        url_for('xx',nid=123)  #反向生成,就会去执行to_url方法
        return "Index"

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

  errorhandler

2、视图函数

恳请和响应

1、diango中的CBV模式

  请求:request

 4858.com 23

  响应:四种 字符串、render_template、redirect、jsonify

2、Flask中的CBV模式

  加响应头就make_response

        def auth(func):
            def inner(*args, **kwargs):
                result = func(*args, **kwargs)
                return result
            return inner

        class IndexView(views.MethodView):
            # methods = ['POST']  #只允许POST请求访问
            decorators = [auth,]  #如果想给所有的get,post请求加装饰器,就可以这样来写,也可以单个指定

            def get(self):   #如果是get请求需要执行的代码
                v = url_for('index')
                print(v)
                return "GET"

            def post(self):  #如果是post请求执行的代码
                return "POST"

        app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  #name指定的是别名,会当做endpoint使用

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

壹、路由和视图

from flask import Flaskduo=Flask(__name__)@duo.route('/index')def index():    print('index')    return 'Index'if __name__ == '__main__':    duo.run()

我们前些天开看看route的源码是什么样体统的:

先不看中间的,发现定义阶段只是回去了 函数decorator的名字

4858.com 24

1、限制性 decorator=duo.route

二、@decorator 那就和装饰器的原理1样,执行的话就把棉被服装饰的函数名字传进去

叁、上海体育场所中的f正是index函数,而rule正是(’/index‘)

4858.com 25

此处就能够看到那么些装饰器实质上正是:

duo.add_url_rule('/index', None, index)

咱俩诠释掉装饰器,就用这一句代码跑跑看,脚本跑起来没难题!

我们继承看。add_url_rule里面包车型客车源码:

4858.com 26

证实了前头说过的为什么endpoint暗中认可景况拾叁分函数名

4858.com 27

得到参数都放到接近一个类,点开看看

4858.com 28

果然是贰个类

4858.com 29

将路有关系添加到全体路由关系映射表

4858.com 30

4858.com 31

总结:

尽量不要让endpoint重名,假诺重名函数一定要平等

3、Flask中的FBV模式

参数:

rule,                       URL规则view_func,                  视图函数名称defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数endpoint=None,              名称,用于反向生成URL,即: url_formethods=None,               允许的请求方式,如:["GET","POST"]strict_slashes=None,        对URL最后的 / 符号是否严格要求,                            @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,           重定向到指定地址                            @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,             子域名访问

CBV:

from flask import Flask,viewsimport functoolsdef wrapper:    @functools.wraps    def inner(*args,**kwargs):        return func(*args,**kwargs)    return innerduo=Flask(__name__)class UserView(views.MethodView):    methods = ['GET']  #只允许GET请求    decorators = [wrapper,]   #加上要执行的装饰器的名字    def get(self,*args,**kwargs):        return 'GET'    def post(self,*args,**kwargs):        return 'POST'duo.add_url_rule('/user',None,UserView.as_view('uuuu'))if __name__ == '__main__':    duo.run()

4858.com 32

差不离大约

4858.com 33

两种办法:

自定义正则:

from  flask import Flask,url_forduo=Flask(__name__)#步骤一:定制类from werkzeug.routing import BaseConverterclass RegexConverter(BaseConverter):    '''    自定义URL匹配正则表达式    '''    def __init__(self,map,regex):        super(RegexConverter,self).__init__        self.regex=regex    def to_python(self, value):        '''        路由匹配时,匹配成功过后传递给视图函数中参数的值        :param value:        :return:        '''        return int    def to_url(self, value):        '''        使用url_for反向生成URL时,传递的参数经过该方法处理,返回值用于生成URL中的参数        :param value:        :return:        '''        val=super(RegexConverter,self).to_url        return val   #完全可以不写#步骤二:添加到转换器duo.url_map.converters['reg']=RegexConverter'''1、用户发送请求2、flask内部进行正则匹配3、调用to_python方法4、to_python的返回值会交给视图函数的参数'''#步骤三:使用自定义正则@duo.route('/index/<reg:nid>')def index:    print(nid,type    print(url_for('index',nid=1))    return 'index'if __name__ == '__main__':    duo.run()
    方式一:
    @app.route('/index',endpoint='xx')
    def index(nid):
        url_for('xx',nid=123)
        return "Index"

    方式二:
    def index(nid):
        url_for('xx',nid=123)
        return "Index"

    app.add_url_rule('/index',index)

二、session完成原理

flask

4858.com 34

4858.com 35

4858.com 36

上边大家来一行行来表达方面猜度的:

4858.com 37

self 是Flask的对象duo,environ请求相关的原本数据

4858.com 38

4858.com 39

4858.com 40

4858.com 41

4858.com 42

4858.com 43

4858.com 44

三、请求与响应

三、蓝图

对象:给开发者提供1个目录结构

壹、首先创设一个和类型一律名字的文书夹,在文书夹中的__init__.py,先定义2个创造对象的函数

from flask import Flaskdef create_app():    duo=Flask(__name__)    return duo

二、在品种1律名字的公文夹下,创建视图像和文字件夹,在其间独自创设须求的功能视图

from flask import Blueprintuc=Blueprint('ac',__name__)@uc.route('/index/')def index():    return 'Index'

三、建立他们之间的涉嫌,在__init__导入生成的靶子 uc,末了注册进去

from flask import Flaskfrom .views.user import ucdef create_app():    duo=Flask(__name__)    duo.register_blueprint(uc,url_prefix='/duoduuo')  #url_prefix适用版本控制       return duo#最后再写一个运行的脚本,

任何的功力:

自定义模板、静态文件

某1类url添加前缀

某一类url添加before_request

4858.com 454858.com 46

④、threading.local(和flask无任何关系)

先看三个简练例子:

import threadingimport timev=0def task:    global v    v=i    time.sleep(1)    printfor i in range(10):    t=threading.Thread(target=task,args=    t.start()#结果都是9,最后一个修改覆盖所有,解决方法加锁

看1种缓解方案:

import threadingfrom threading import local#为每给线程创建一个独立空间来修改数据,使得线程对自己的空间中的数据进行操作import timeobj=local()def task:    obj.duo=i    time.sleep(1)    print(obj.duo,i)for i in range(10):    t=threading.Thread(target=task,args=    t.start()

今昔大家来设想几个难题,

哪些获取三个线程的唯1标记 ?

threading.get_ident()  #跟linux进程pid类似

根据字典自定义二个像样于threading.local功能?

因此getattr,setattr 营造出加强版的threading.local作用!

import  timeimport threadingtry:    import greenlet      #有就是协程,没有就是线程    get_ident=greenlet.getcurrentexcept Exception as e:    get_ident=threading.get_identclass Local:    DIC={}    def __getattr__(self, item):    #self.xxx  触发执行        # print('getattr',item)        ident=get_ident()        if ident in self.DIC:            return self.DIC[ident].get        return None    def __setattr__(self, key, value):    #self.xxx=123  触发执行        # print('setattr',key,value)        ident=get_ident()        if ident in self.DIC:            self.DIC[ident][key]=value        else:            self.DIC[ident]={key:value}obj=Local()def task:    obj.duo=i    time.sleep(1)    print(obj.duo,i)for i in range(10):    t=threading.Thread(target=task,args=    t.start()

后续照旧有看源码的博客:

 1 from flask import Flask
 2     from flask import request
 3     from flask import render_template
 4     from flask import redirect
 5     from flask import make_response
 6 
 7     app = Flask(__name__)
 8 
 9 
10     @app.route('/login.html', methods=['GET', "POST"])
11     def login():
12 
13         # 请求相关信息
14         # request.method
15         # request.args
16         # request.form
17         # request.values
18         # request.cookies
19         # request.headers
20         # request.path
21         # request.full_path
22         # request.script_root
23         # request.url
24         # request.base_url
25         # request.url_root
26         # request.host_url
27         # request.host
28         # request.files
29         # obj = request.files['the_file_name']
30         # obj.save('/var/www/uploads/' + secure_filename(f.filename))
31 
32         # 响应相关信息
33         # return "字符串"
34         # return render_template('html模板路径',**{})
35         # return redirect('/index.html')
36 
37         # response = make_response(render_template('index.html'))
38         # response是flask.wrappers.Response类型
39         # response.delete_cookie('key')
40         # response.set_cookie('key', 'value')
41         # response.headers['X-Something'] = 'A value'
42         # return response
43 
44 
45         return "内容"
46 
47     if __name__ == '__main__':
48         app.run()

伍、简述上下文物管理理

1、当呼吁到来时,在源码中wsgi_app 中 ctx
对象是RequestContext封装全数的目的和乞请相关的固有数据,

这几个目的就有request和session,在接下去的对session举办填补,将富含了request/session的ctx对象放置’神奇的地点‘

其一神奇的地点正是1个大字典,用线程或协程的唯一标识为key,

二、当视图函数使用的时候:

假使取二个request.method ,我们开头入 from flask import request
,依照当前线程取ctx对象,再取request,再取.method

三、当呼吁截至:

依照近期线程的绝无仅有标记,将’神奇地点‘上的多少移除

View Code

 

from flask import Flask,url_for,request,redirect,render_template,jsonify,make_response
from urllib.parse import urlencode,quote,unquote
app = Flask(__name__)

@app.route('/index',endpoint='xx')
def index():
    from werkzeug.datastructures import ImmutableMultiDict
  =================
    # get_data = request.args
    # get_dict = get_data.to_dict()
    # get_dict['xx'] = '18'
    # url = urlencode(get_dict)
    # print(url)
  ====================
    # print(request.query_string)
    # print(request.args)
  ==========================
    # val = "%E6%8A%8A%E5%87%A0%E4%B8%AA"
    # print(unquote(val))   #吧上面这样的数据转换成中文
    #
    # return "Index"

    # return "Index"
    # return redirect()
    # return render_template()
    # return jsonify(name='alex',age='18')  #相当于JsonResponse
  =======================
    response = make_response('xxxxx')   ##如果是返回更多的值,cookie,headers,或者其他的就可用它
    response.headers['xxx'] = '123123'
    return response


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

四、模板语法

一、为了防患xss攻击,加了验证,所以页面上出示字符串的情势,消除办法,有三种方法

  - 在后端Markup

 v5 = Markup("<input type='text' />")

  - 在前端

  {{ v4|safe }}

二、自定义方法

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

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


index2.html
<h1>{{ test(1,2) }}</h1>

三、写二个函数在具有的页面都采纳

template_global和template_filter

@app.template_global()
def sb(a1, a2):
    return a1 + a2


@app.template_filter()
def db(a1, a2, a3):
    return a1 + a2 + a3

调用方式:{{sb(1,2)}}  {{ 1|db(2,3)}}

肆、模板继承:和django的均等。extents

5、宏:唯有定义的事物在不少地点去采取的时候才去用它

{% macro input(name, type='text', value='') %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

{{ input('n1') }}  

 练习:  

4858.com 474858.com 48

 1 from flask import Flask,url_for,render_template,Markup
 2 app = Flask(__name__)
 3 
 4 def test(a,b):
 5     return a+b
 6 
 7 @app.template_global()
 8 def sb(a1, a2):
 9     return a1 + a2 + 100
10 
11 
12 @app.template_filter()
13 def db(a1, a2, a3):
14     return a1 + a2 + a3
15 
16 @app.route('/index')
17 def index():
18     v1 = "字符串"
19     v2 = [11,22,33]
20     v3 = {"k1":"v3","sdf":"sdgfgf"}
21     v4 = "<input type='text' />"
22     v5 = Markup("<input type='text' />")
23     return render_template("index2.html",v1=v1,v2=v2,v3=v3,v4=v4,v5=v5,test=test)
24 
25 if __name__ == '__main__':
26     app.run(debug=True)

模板语法

4858.com 494858.com 50

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width">
 7     <title>Title</title>
 8 </head>
 9 <body>
10 {{ v1 }}
11 <ul>
12     {% for foo in v2 %}
13        <li>{{ foo }}</li>
14     {% endfor %}
15     {{ v2.1 }}
16 
17     {% for k,v in v3.items() %}
18     <li>{{ k }} {{ v }}</li>
19     {% endfor %}
20     {{ v3.k1 }}
21     {{ v3.get("k1") }}
22 
23     {{ v4|safe }}
24     {{ v5 }}
25 
26     <h1>{{ test(1,2) }}</h1>
27     <p>{{ sb(1,2) }}</p>
28     <p>{{ 1| db(2,3) }}</p>
29 </ul>
30 </body>
31 </html>

index2.html

五、session

除请求对象之外,还有二个 session
对象。它同意你在不相同请求间存款和储蓄特定用户的音讯。它是在 Cookies
的基础上贯彻的,并且对 库克ies
进行密钥签名要选择会话,你需求安装1个密钥。

  • 设置:session[‘username’] = ‘xxx’

  • 删除:session.pop(‘username’, None)

    from flask import Flask,url_for,session

    app = Flask(name)
    app.secret_key = “sdsfdgdgdgd”
    app.config[‘SESSION_COOKIE_NAME’] = ‘session_lvning’ #设置session的名字

    @app.route(‘/index/’)
    def index(nid):

    #session本质上操作的是字典, session是否还有其他方法?与字典方法相同
    #session的原理:如果下一次访问的时候带着随机字符串,会把session里面对应的
    # 值拿到内存,假设session保存在数据库,每执行一次链接一次数据库,每次都要时时更新的话
    # 会非常损耗内存
    session["xxx"] = 123
    session["xxx2"] = 123
    session["xxx3"] = 123
    session["xxx4"] = 123
    del session["xxx2"]  #在这删除了,真正存储的时候是没有xxx2的
    return "ddsf"
    

    if name == ‘main‘:

    app.run()
    

关于session的配置

 app.config['SESSION_COOKIE_NAME'] = 'session_lvning'

- session超时时间如何设置?      'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)

 以下是跟session相关的配置文件

"""
            'SESSION_COOKIE_NAME':                  'session',
            'SESSION_COOKIE_DOMAIN':                None,
            'SESSION_COOKIE_PATH':                  None,
            'SESSION_COOKIE_HTTPONLY':              True,
            'SESSION_COOKIE_SECURE':                False,
            'SESSION_REFRESH_EACH_REQUEST':         True,  #是否每次都跟新
            'PERMANENT_SESSION_LIFETIME':           timedelta(days=31)

4858.com 514858.com 52

 1 from flask import Flask, session, redirect, url_for, escape, request
 2  
 3 app = Flask(__name__)
 4  
 5 @app.route('/')
 6 def index():
 7     if 'username' in session:
 8         return 'Logged in as %s' % escape(session['username'])
 9     return 'You are not logged in'
10  
11 @app.route('/login', methods=['GET', 'POST'])
12 def login():
13     if request.method == 'POST':
14         session['username'] = request.form['username']
15         return redirect(url_for('index'))
16     return '''
17         <form action="" method="post">
18             <p><input type=text name=username>
19             <p><input type=submit value=Login>
20         </form>
21     '''
22  
23 @app.route('/logout')
24 def logout():
25     # remove the username from the session if it's there
26     session.pop('username', None)
27     return redirect(url_for('index'))
28  
29 # set the secret key.  keep this really secret:
30 app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

骨干使用

4858.com 534858.com 54

  1 pip3 install Flask-Session
  2         
  3         run.py
  4             from flask import Flask
  5             from flask import session
  6             from pro_flask.utils.session import MySessionInterface
  7             app = Flask(__name__)
  8 
  9             app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
 10             app.session_interface = MySessionInterface()
 11 
 12             @app.route('/login.html', methods=['GET', "POST"])
 13             def login():
 14                 print(session)
 15                 session['user1'] = 'alex'
 16                 session['user2'] = 'alex'
 17                 del session['user2']
 18 
 19                 return "内容"
 20 
 21             if __name__ == '__main__':
 22                 app.run()
 23 
 24         session.py
 25             #!/usr/bin/env python
 26             # -*- coding:utf-8 -*-
 27             import uuid
 28             import json
 29             from flask.sessions import SessionInterface
 30             from flask.sessions import SessionMixin
 31             from itsdangerous import Signer, BadSignature, want_bytes
 32 
 33 
 34             class MySession(dict, SessionMixin):
 35                 def __init__(self, initial=None, sid=None):
 36                     self.sid = sid
 37                     self.initial = initial
 38                     super(MySession, self).__init__(initial or ())
 39 
 40 
 41                 def __setitem__(self, key, value):
 42                     super(MySession, self).__setitem__(key, value)
 43 
 44                 def __getitem__(self, item):
 45                     return super(MySession, self).__getitem__(item)
 46 
 47                 def __delitem__(self, key):
 48                     super(MySession, self).__delitem__(key)
 49 
 50 
 51 
 52             class MySessionInterface(SessionInterface):
 53                 session_class = MySession
 54                 container = {}
 55 
 56                 def __init__(self):
 57                     import redis
 58                     self.redis = redis.Redis()
 59 
 60                 def _generate_sid(self):
 61                     return str(uuid.uuid4())
 62 
 63                 def _get_signer(self, app):
 64                     if not app.secret_key:
 65                         return None
 66                     return Signer(app.secret_key, salt='flask-session',
 67                                   key_derivation='hmac')
 68 
 69                 def open_session(self, app, request):
 70                     """
 71                     程序刚启动时执行,需要返回一个session对象
 72                     """
 73                     sid = request.cookies.get(app.session_cookie_name)
 74                     if not sid:
 75                         sid = self._generate_sid()
 76                         return self.session_class(sid=sid)
 77 
 78                     signer = self._get_signer(app)
 79                     try:
 80                         sid_as_bytes = signer.unsign(sid)
 81                         sid = sid_as_bytes.decode()
 82                     except BadSignature:
 83                         sid = self._generate_sid()
 84                         return self.session_class(sid=sid)
 85 
 86                     # session保存在redis中
 87                     # val = self.redis.get(sid)
 88                     # session保存在内存中
 89                     val = self.container.get(sid)
 90 
 91                     if val is not None:
 92                         try:
 93                             data = json.loads(val)
 94                             return self.session_class(data, sid=sid)
 95                         except:
 96                             return self.session_class(sid=sid)
 97                     return self.session_class(sid=sid)
 98 
 99                 def save_session(self, app, session, response):
100                     """
101                     程序结束前执行,可以保存session中所有的值
102                     如:
103                         保存到resit
104                         写入到用户cookie
105                     """
106                     domain = self.get_cookie_domain(app)
107                     path = self.get_cookie_path(app)
108                     httponly = self.get_cookie_httponly(app)
109                     secure = self.get_cookie_secure(app)
110                     expires = self.get_expiration_time(app, session)
111 
112                     val = json.dumps(dict(session))
113 
114                     # session保存在redis中
115                     # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
116                     # session保存在内存中
117                     self.container.setdefault(session.sid, val)
118 
119                     session_id = self._get_signer(app).sign(want_bytes(session.sid))
120 
121                     response.set_cookie(app.session_cookie_name, session_id,
122                                         expires=expires, httponly=httponly,
123                                         domain=domain, path=path, secure=secure)

自定义Session

4858.com 554858.com 56

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 """
 4 pip3 install redis
 5 pip3 install flask-session
 6 
 7 """
 8 
 9 
10 from flask import Flask, session, redirect
11 from flask.ext.session import Session
12 
13 
14 app = Flask(__name__)
15 app.debug = True
16 app.secret_key = 'asdfasdfasd'
17 
18 
19 app.config['SESSION_TYPE'] = 'redis'
20 from redis import Redis
21 app.config['SESSION_REDIS'] = Redis(host='192.168.0.94',port='6379')
22 Session(app)
23 
24 
25 @app.route('/login')
26 def login():
27     session['username'] = 'alex'
28     return redirect('/index')
29 
30 
31 @app.route('/index')
32 def index():
33     name = session['username']
34     return name
35 
36 
37 if __name__ == '__main__':
38     app.run()

第三方session

六、blueprint,蓝图

七、闪现 :
flash 

session存在在服务端的四个字典里面,session保存起来,取一回里面只怕有些,直到你剔除之后才未有了

1、本质:flash是基于session制造的,flash帮助往中间放值,只要你取一下就没有了,也就是pop了弹指间。不仅吧值取走,而且吧session里的事物去掉

二、闪现有啥用?

from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
app = Flask(__name__)
app.secret_key ='sdfsdfsdf'

@app.route('/users')
def users():
    # 方式一
    # msg = request.args.get('msg','')
    # 方式二
    # msg = session.get('msg')
    # if msg:
    #     del session['msg']
    # 方式三
    v = get_flashed_messages()
    print(v)
    msg = ''
    return render_template('users.html',msg=msg)

@app.route('/useradd')
def user_add():
    # 在数据库中添加一条数据
    # 假设添加成功,在跳转到列表页面时,显示添加成功
    # 方式一
    # return redirect('/users?msg=添加成功')
    # 方式二
    # session['msg'] = '添加成功'
    # 方式三
    flash('添加成功')
    return redirect('/users')


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

 八、扩展

一、在函数执行以前或函数执行之后做点事情

第一种:装饰器

其次种:flask里面包车型地铁扩充,也正是django中的中间件

from flask import Flask,session,Session,flash,get_flashed_messages,redirect,render_template,request
app = Flask(__name__)
app.secret_key ='sdfsdfsdf'

@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('/index')
def index():
    print('index')
    return 'Index'

@app.route('/order')
def order():
    print('order')
    return 'order'

@app.route('/test')
def test():
    print('test')
    return 'test'

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

运维结果:

4858.com 57

再有3个@app.before_first_request:表示,当程序运维起来,第3个请求来的时候就只进行二回,下次再来就不会在进行了

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有