zoukankan      html  css  js  c++  java
  • python之路_flask框架_flask-session组件、信号及wtforms组件

    一、flask-session组件

      我们知道,在flask的内置session中,是存到加密cookie中。但是我们怎样么才可以将session在服务器也保存呢?之前我们也说过,自定义的session可以将键值对保存在内存中,但是想要实现在服务端永久的保存起来,我们就可以利用flask-session组件。利用此组件可以将session保存在redis、文件memcache等,如下列出主要的使用配置。

    1、redis保存

    from flask import Flask,session
    from flask_session import Session
    import redis
    app=Flask(__name__)
    # 为Flask-session组件提供的配置
    app.config['SESSION_TYPE'] = 'redis'                     # session类型为redis
    app.config['SESSION_REDIS'] = redis.Redis(host='127.0.0.1', port='6379', password='123123')  # 用于连接redis的配置
    app.config['SESSION_KEY_PREFIX'] = 'session:'            # 保存到session中的值的前缀
    app.config['SESSION_PERMANENT'] = False                  # 如果设置为True,则关闭浏览器session就失效。
    app.config['SESSION_USE_SIGNER'] = False                 # 是否对发送到浏览器上 session:cookie值进行加密
    Session(app)
    
    @app.route("/index/")
    def index():
        session["k1"]="v1"                                   #正常设置session
        return "ok"
    if __name__ == '__main__':
        app.run()

    2、文件保存

    from flask import Flask,session
    from flask_session import Session
    app=Flask(__name__)
    # 为Flask-session组件提供的配置
    app.config['SESSION_TYPE'] = 'filesystem'               # session类型为文件
    app.config['SESSION_FILE_DIR'] = r'D:PycharmProjectsflask_day05flask-session组件'  # 文件路径
    app.config['SESSION_FILE_THRESHOLD'] = 500              # 存储session的个数如果大于这个值时,就要开始进行删除了
    app.config['SESSION_FILE_MODE'] = 384                   # 文件权限类型
    
    app.config['SESSION_PERMANENT'] = True                  # 如果设置为True,则关闭浏览器session就失效。
    app.config['SESSION_USE_SIGNER'] = False                # 是否对发送到浏览器上session的cookie值进行加密
    app.config['SESSION_KEY_PREFIX'] = 'session:'           # 保存到session中的值的前缀
    
    Session(app)
    
    @app.route("/index/")
    def index():
        session["k1"]="v1"                                  #正常设置session
        return "ok"
    if __name__ == '__main__':
        app.run()

    3、memcache保存

      主要配置如下,使用方式如上实例相同。

    import memcache
    app.config['SESSION_TYPE'] = 'memcached'               # session类型为memcached
    app.config['SESSION_PERMANENT'] = True                 # 如果设置为True,则关闭浏览器session就失效。
    app.config['SESSION_USE_SIGNER'] = False               # 是否对发送到浏览器上session的cookie值进行加密
    app.config['SESSION_KEY_PREFIX'] = 'session:'          # 保存到session中的值的前缀
    app.config['SESSION_MEMCACHED'] = memcache.Client(['10.211.55.4:12000'])
    Session(app)

    二、信号

      Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为。它与flask中的特殊装饰器不同的地方在于,信号没有返回值,而特殊装饰器是可以有返回值的,且返回值是有意义 。利用信号可以降低代码之间的耦合。安装方式为:pip3 install blinker。

    1、内置信号

      如下列出了flask内置的10个信号,其中序号表示信号被触发的顺序。

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

    2、自定义信号

    from flask import Flask
    from flask.signals import _signals
    app = Flask(__name__)
    
    mysignal= _signals.signal('mysignal')                        #自定义信号
    
    # 定义函数
    def foo(*args,**kwargs):
        print('罗姑娘',args,kwargs)
    # 定义函数
    def bar(*args,**kwargs):
        print('少姑娘',args,kwargs)
    
    # 将函数注册到自定义信号中: 添加到这个列表
    mysignal.connect(foo)
    mysignal.connect(bar)
    
    @app.route('/index/')
    def index():
        # 触发这个信号:执行注册到列表中的所有函数
        mysignal.send(000,a1=123,a2=456)                          #send为触发信号的方法,传自定义函数需要的参数
        return "xx"
    
    if __name__ == '__main__':
        app.run()

    三、wtforms组件

      在django中我们熟悉了forms组件,利用他可以实现对表单数据的校验,我们将要介绍wtforms组件和django的forms组件相似,实现的功能是一样的。WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证。安装如下:pip3 install wtforms,具体的使用分别以用户登录和注册实例介绍:

    1、登录实例

    后端代码:

    from flask import Flask,render_template,request
    from wtforms import Form,widgets,validators
    from wtforms.fields import core,html5,simple
    
    app=Flask(__name__)
    
    class LoginForm(Form):
        name=simple.StringField(
            label="用户名",
            validators=[
                validators.DataRequired(message="用户名不能为空"),
                validators.Length(min=6,max=10,message="用户名长度必须大于%(min)d,小于%(max)d")
            ],
            widget=widgets.TextInput(),
            render_kw={"class":"form-control"}
        )
        password=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=="POST":
            form=LoginForm(request.form)
            if form.validate():
                print(form.data)
                return "登陆成功"
            else:
                print(form.errors)
                return render_template("login.html",form=form)
        else:
            form=LoginForm()
            return render_template("login.html",form=form)
        
    if __name__ == '__main__':
        app.run()

    前端代码:

    2、注册实例

      后端实例如下,包含可能需要渲染的标签类型。前端渲染方式如登录实例。

    from flask import Flask,render_template,request
    from wtforms import Form,widgets,validators
    from wtforms.fields import core,html5,simple
    
    app=Flask(__name__)
    
    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
        )
        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=="POST":
            form=RegisterForm(request.form)
            if form.validate():
                print(form.data)
                return "注册成功"
            else:
                print(form.errors)
                return render_template("register.html",form=form)
        else:
            form = RegisterForm(data={'gender': 1})               # 可以通过data设置默认值
            return render_template("register.html" ,form=form)
    
    
    if __name__ == '__main__':
        app.run()

    3、自定义校验类

      参考源码中校验的实现的方式,我们也可以自己实现自定义校验规则,参考如下实例:

    
    
    #自定义姓名是否为王浩的校验类
    class MyValidator(object):
        def __init__(self,message):
            self.message = message
        def __call__(self, form, field):
            print(field.data)
            if field.data == '王浩':
                return None
            raise validators.StopValidation(self.message)
    
    
    class LoginForm(Form):
        name = simple.StringField(
            label='用户名',
            validators=[
                MyValidator(message='用户名必须等于王浩')                          #自定义校验类的使用
                validators.DataRequired(message='用户名不能为空.'),
                validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d')
            ],
            widget=widgets.TextInput(),
            render_kw={'class': 'form-control'}
        )
  • 相关阅读:
    Vue路由重定向
    Vue使用rules对表单字段进行校验
    CSS Flex弹性布局实现Div
    Leetcode5 最长回文子串
    Java中char与String的相互转换
    [剑指offer] 替换空格
    Leetode最长回文串
    JavaScript 常用正则表达式集锦
    JavaScript 函数节流
    JavaScript target 与 currentTarget 区别
  • 原文地址:https://www.cnblogs.com/seven-007/p/8407070.html
Copyright © 2011-2022 走看看