zoukankan      html  css  js  c++  java
  • Flask_____

    flask-session

    作用:将默认保存的签名cookie中的值 保存到 redis/memcached/file/Mongodb/SQLAlchemy

    安装:pip3 install flask-session

    使用1:

    from flask import Flask,session
    from flask_session import RedisSessionInterface
    import redis
    app = Flask(__name__)
    conn=redis.Redis(host='127.0.0.1',port=6379)
    #use_signer是否对key签名
    app.session_interface=RedisSessionInterface(conn,key_prefix='lqz')
    @app.route('/')
    def hello_world():
        session['name']='lqz'
        return 'Hello World!'
    
    if __name__ == '__main__':
        app.run()

    使用2:

    from redis import Redis
    from flask.ext.session import Session
    app.config['SESSION_TYPE'] = 'redis'
    app.config['SESSION_REDIS'] = Redis(host='192.168.0.94',port='6379')
    Session(app)

    问题:设置cookie时,如何设定关闭浏览器则cookie失效。

    response.set_cookie('k','v',exipre=None)#这样设置即可
    #在session中设置
    app.session_interface=RedisSessionInterface(conn,key_prefix='lqz',permanent=False)
    #一般不用,我们一般都设置超时时间,多长时间后失效

    问题:cookie默认超时时间是多少?如何设置超时时间

    #源码expires = self.get_expiration_time(app, session)
    'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),#这个配置文件控制

    数据库连接池

    pymsql链接数据库

    import pymysql
    
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='s8day127db')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # cursor.execute("select id,name from users where name=%s and pwd=%s",['lqz','123',])
    cursor.execute("select id,name from users where name=%(user)s and pwd=%(pwd)s",{'user':'lqz','pwd':'123'})
    obj = cursor.fetchone()
    conn.commit()
    cursor.close()
    conn.close()
    
    print(obj)

    数据库连接池版

    setting.py

    from datetime import timedelta
    from redis import Redis
    import pymysql
    from DBUtils.PooledDB import PooledDB, SharedDBConnection
    
    class Config(object):
        DEBUG = True
        SECRET_KEY = "umsuldfsdflskjdf"
        PERMANENT_SESSION_LIFETIME = timedelta(minutes=20)
        SESSION_REFRESH_EACH_REQUEST= True
        SESSION_TYPE = "redis"
        PYMYSQL_POOL = PooledDB(
            creator=pymysql,  # 使用链接数据库的模块
            maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数
            mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
            maxcached=5,  # 链接池中最多闲置的链接,0和None不限制
            maxshared=3,
            # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
            blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
            maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制
            setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
            ping=0,
            # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
            host='127.0.0.1',
            port=3306,
            user='root',
            password='123456',
            database='s8day127db',
            charset='utf8'
        )
    
    class ProductionConfig(Config):
        SESSION_REDIS = Redis(host='192.168.0.94', port='6379')
    
    
    
    class DevelopmentConfig(Config):
        SESSION_REDIS = Redis(host='127.0.0.1', port='6379')
    
    
    class TestingConfig(Config):
        pass

    utils/sql.py

    import pymysql
    from settings import Config
    class SQLHelper(object):
    
        @staticmethod
        def open(cursor):
            POOL = Config.PYMYSQL_POOL
            conn = POOL.connection()
            cursor = conn.cursor(cursor=cursor)
            return conn,cursor
    
        @staticmethod
        def close(conn,cursor):
            conn.commit()
            cursor.close()
            conn.close()
    
        @classmethod
        def fetch_one(cls,sql,args,cursor =pymysql.cursors.DictCursor):
            conn,cursor = cls.open(cursor)
            cursor.execute(sql, args)
            obj = cursor.fetchone()
            cls.close(conn,cursor)
            return obj
    
        @classmethod
        def fetch_all(cls,sql, args,cursor =pymysql.cursors.DictCursor):
            conn, cursor = cls.open(cursor)
            cursor.execute(sql, args)
            obj = cursor.fetchall()
            cls.close(conn, cursor)
            return obj

    使用:

    obj = SQLHelper.fetch_one("select id,name from users where name=%(user)s and pwd=%(pwd)s", form.data)

    wtforms

    安装:pip3 install wtforms

    使用1:

    from flask import Flask, render_template, request, redirect
    from wtforms import Form
    from wtforms.fields import simple
    from wtforms import validators
    from wtforms import widgets
    
    app = Flask(__name__, template_folder='templates')
    
    app.debug = True
    
    
    class LoginForm(Form):
        # 字段(内部包含正则表达式)
        name = simple.StringField(
            label='用户名',
            validators=[
                validators.DataRequired(message='用户名不能为空.'),
                validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d')
            ],
            widget=widgets.TextInput(), # 页面上显示的插件
            render_kw={'class': 'form-control'}
    
        )
        # 字段(内部包含正则表达式)
        pwd = simple.PasswordField(
            label='密码',
            validators=[
                validators.DataRequired(message='密码不能为空.'),
                validators.Length(min=8, message='用户名长度必须大于%(min)d'),
                validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[$@$!%*?&])[A-Za-zd$@$!%*?&]{8,}",
                                  message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符')
    
            ],
            widget=widgets.PasswordInput(),
            render_kw={'class': 'form-control'}
        )
    
    
    
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'GET':
            form = LoginForm()
            return render_template('login.html', form=form)
        else:
            form = LoginForm(formdata=request.form)
            if form.validate():
                print('用户提交数据通过格式验证,提交的值为:', form.data)
            else:
                print(form.errors)
            return render_template('login.html', form=form)
    
    if __name__ == '__main__':
        app.run()

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>登录</h1>
    <form method="post">
        <p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p>
    
        <p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p>
        <input type="submit" value="提交">
    </form>
    </body>
    </html>

    使用2:

    from flask import Flask, render_template, request, redirect
    from wtforms import Form
    from wtforms.fields import core
    from wtforms.fields import html5
    from wtforms.fields import simple
    from wtforms import validators
    from wtforms import widgets
    
    app = Flask(__name__, template_folder='templates')
    app.debug = True
    
    
    
    class RegisterForm(Form):
        name = simple.StringField(
            label='用户名',
            validators=[
                validators.DataRequired()
            ],
            widget=widgets.TextInput(),
            render_kw={'class': 'form-control'},
            default='alex'
        )
    
        pwd = simple.PasswordField(
            label='密码',
            validators=[
                validators.DataRequired(message='密码不能为空.')
            ],
            widget=widgets.PasswordInput(),
            render_kw={'class': 'form-control'}
        )
    
        pwd_confirm = simple.PasswordField(
            label='重复密码',
            validators=[
                validators.DataRequired(message='重复密码不能为空.'),
                validators.EqualTo('pwd', message="两次密码输入不一致")
            ],
            widget=widgets.PasswordInput(),
            render_kw={'class': 'form-control'}
        )
    
        email = html5.EmailField(
            label='邮箱',
            validators=[
                validators.DataRequired(message='邮箱不能为空.'),
                validators.Email(message='邮箱格式错误')
            ],
            widget=widgets.TextInput(input_type='email'),
            render_kw={'class': 'form-control'}
        )
    
        gender = core.RadioField(
            label='性别',
            choices=(
                (1, ''),
                (2, ''),
            ),
            coerce=int # “1” “2”
         )
        city = core.SelectField(
            label='城市',
            choices=(
                ('bj', '北京'),
                ('sh', '上海'),
            )
        )
    
        hobby = core.SelectMultipleField(
            label='爱好',
            choices=(
                (1, '篮球'),
                (2, '足球'),
            ),
            coerce=int
        )
    
        favor = core.SelectMultipleField(
            label='喜好',
            choices=(
                (1, '篮球'),
                (2, '足球'),
            ),
            widget=widgets.ListWidget(prefix_label=False),
            option_widget=widgets.CheckboxInput(),
            coerce=int,
            default=[1, 2]
        )
    
        def __init__(self, *args, **kwargs):
            super(RegisterForm, self).__init__(*args, **kwargs)
            self.favor.choices = ((1, '篮球'), (2, '足球'), (3, '羽毛球'))
    
        def validate_pwd_confirm(self, field):
            """
            自定义pwd_confirm字段规则,例:与pwd字段是否一致
            :param field:
            :return:
            """
            # 最开始初始化时,self.data中已经有所有的值
    
            if field.data != self.data['pwd']:
                # raise validators.ValidationError("密码不一致") # 继续后续验证
                raise validators.StopValidation("密码不一致")  # 不再继续后续验证
    
    
    @app.route('/register', methods=['GET', 'POST'])
    def register():
        if request.method == 'GET':
            form = RegisterForm(data={'gender': 2,'hobby':[1,]}) # initial
            return render_template('register.html', form=form)
        else:
            form = RegisterForm(formdata=request.form)
            if form.validate():
                print('用户提交数据通过格式验证,提交的值为:', form.data)
            else:
                print(form.errors)
            return render_template('register.html', form=form)
    
    
    
    if __name__ == '__main__':
        app.run()

    register.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>用户注册</h1>
    <form method="post" novalidate style="padding:0  50px">
        {% for field in form %}
        <p>{{field.label}}: {{field}} {{field.errors[0] }}</p>
        {% endfor %}
        <input type="submit" value="提交">
    </form>
    </body>
    </html>

    信号

    Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为

    安装:pip3 install blinker

    内置信号:

    request_started = _signals.signal('request-started')                # 请求到来前执行
    request_finished = _signals.signal('request-finished')              # 请求结束后执行
     
    before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行
    template_rendered = _signals.signal('template-rendered')            # 模板渲染后执行
     
    got_request_exception = _signals.signal('got-request-exception')    # 请求执行出现异常时执行
     
    request_tearing_down = _signals.signal('request-tearing-down')      # 请求执行完毕后自动执行(无论成功与否)
    appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 应用上下文执行完毕后自动执行(无论成功与否)
     
    appcontext_pushed = _signals.signal('appcontext-pushed')            # 应用上下文push时执行
    appcontext_popped = _signals.signal('appcontext-popped')            # 应用上下文pop时执行
    message_flashed = _signals.signal('message-flashed')                # 调用flask在其中添加数据时,自动触发

    使用信号:

    from flask import Flask,signals,render_template
    
    app = Flask(__name__)
    
    # 往信号中注册函数
    def func(*args,**kwargs):
        print('触发型号',args,kwargs)
    signals.request_started.connect(func)
    
    # 触发信号: signals.request_started.send()
    @app.before_first_request
    def before_first1(*args,**kwargs):
        pass
    @app.before_first_request
    def before_first2(*args,**kwargs):
        pass
    
    @app.before_request
    def before_first3(*args,**kwargs):
        pass
    
    @app.route('/',methods=['GET',"POST"])
    def index():
        print('视图')
        return render_template('index.html')
    
    
    if __name__ == '__main__':
        app.wsgi_app
        app.run()
    -内置信号:
        #第一步,编写一个函数
        def func(*
    args,**kwargs):
            print('触发信号',args,kwargs)
        #第二步:注册信号
        #signals.request_started.connect(func)
        signals.request_finished.connect(func)
     
    -自定义信号:
        #第一步:定义信号
        aaa = _signals.signal('aaa')
        #第二步:编写函数,绑定信息
        def func(*args,**kwargs):
            print('信号',args,kwargs)
        #第三步,绑定函数
        aaa.connect(func)
        #触发信号
        aaa.send('123123',k1='v1')

    自定义信号(了解):

    from flask import Flask, current_app, flash, render_template
    from flask.signals import _signals
    app = Flask(import_name=__name__)
    
    # 自定义信号
    xxxxx = _signals.signal('xxxxx')
     
    def func(sender, *args, **kwargs):
        print(sender)
    # 自定义信号中注册函数
    xxxxx.connect(func)
    @app.route("/x")
    def index():
        # 触发信号
        xxxxx.send('123123', k1='v1')
        return 'Index' 
     
    if __name__ == '__main__':
        app.run()

    多app应用

    from werkzeug.wsgi import DispatcherMiddleware
    from werkzeug.serving import run_simple
    from flask import Flask, current_app
    app1 = Flask('app01')
    app2 = Flask('app02')
    
    @app1.route('/index')
    def index():
        return "app01"
    
    @app2.route('/index2')
    def index2():
        return "app2"
    
    # http://www.oldboyedu.com/index
    # http://www.oldboyedu.com/sec/index2
    dm = DispatcherMiddleware(app1, {
        '/sec': app2,
    })
    
    if __name__ == "__main__":
        run_simple('localhost', 5000, dm)

    flask-script

    用于实现类似于django中 python3 manage.py runserver ...类似的命令

    安装:pip3 install flask-script

    from flask_script import Manager
    app = Flask(__name__)
    manager=Manager(app)
    ...
    if __name__ == '__main__':
        manager.run()
    #以后在执行,直接:python3 manage.py runserver
    #python3 manage.py runserver --help

    自定制命令

    @manager.command
    def custom(arg):
        """
        自定义命令
        python manage.py custom 123
        :param arg:
        :return:
        """
        print(arg)
    
    
    @manager.option('-n', '--name', dest='name')
    #@manager.option('-u', '--url', dest='url')
    def cmd(name, url):
        """
        自定义命令(-n也可以写成--name)
        执行: python manage.py  cmd -n lqz -u http://www.oldboyedu.com
        执行: python manage.py  cmd --name lqz --url http://www.oldboyedu.com
        :param name:
        :param url:
        :return:
        """
        print(name, url)
    #有什么用?
    #把excel的数据导入数据库,定制个命令,去执行
  • 相关阅读:
    【高级内部资料】.NET数据批量写入性能分析 第二篇
    负载均衡原理与实践详解 第五篇 负载均衡时数据包流程详解
    负载均衡原理与实践详解 第三篇 服务器负载均衡的基本概念网络基础
    如何提高Linq查询的性能(上)
    【全面解析DeepZoom 之二】Silverlight2及Deep Zoom环境的搭建
    关于让WPF软件界面支持全球化和本地化
    在WPF中自定义控件(3) CustomControl (上)
    【全面解析DeepZoom 之一】酷!Deep Zoom
    谈谈我理解的WPF团队模型——在UI Designer与Developer之间
    [WPF疑难]在WPF中显示动态GIF
  • 原文地址:https://www.cnblogs.com/KrisYzy/p/11857899.html
Copyright © 2011-2022 走看看