zoukankan      html  css  js  c++  java
  • flask之三方组件

    Flask-session

    Flask-session跟框架自带的session有什么区别呢

    框架自带的session是通过请求上下文~放入到Local中的~那如果我们想把session放入别的地方怎么办呢

    比如redis~或者数据库~等等~~Flask-session就提供了这些功能~~我们看下Flask-session怎么用

    一、下载安装

    pip install flask-session

    二、导入并实例化

    def create_app():
        app = Flask(__name__)
        app.config.from_object("settings.BaseConfig")
    
        app.register_blueprint(us)
        # Flask-Session 第二步实例化session
        Session(app)
       
        return app

    三、配置文件

    class BaseConfig(object):
        # Flask-Session  第三步
        # SESSION_TYPE = 'redis'
        # SESSION_REDIS = Redis(host='192.168.0.94', port='6379')

    四、实现原理

    回顾一下session的实现原理~请求进来先把request以及session封装到RequestContext对象中~

    然后调用push方法通过LocalStark放入到Local中~这时候放入到Local中的session还是空的~

    然后调用了session_interface中的open_session 以及save_session方法~

    再看下~~Flask-session都做了什么~

    修改了app.session_interface这个类~所以在我们调用open_session以及save_session的时候~调用的是我们配置的类里的方法~

    从而实现了session存储地方的不同~

    Flask SQLAlchemy

    学习Flask-SQLAlchemy前的想学习SQLAlchemy

    这是一个Python的ORM框架, 详情见上篇博客

    附地址 SQLAlchemy : https://www.cnblogs.com/peng104/p/10211858.html

     接下来才是Flask-SQLAlchemy的应用

    一、下载安装

    pip3 install flask-sqlalchemy

    二、导入并实例化SQLAlchemy

    # 在跟项目同名的文件夹下的 init.py中
    from flask_sqlalchemy import SQLAlchemy
    db = SQLAlchemy()
    
    from .views.user import us
    
    # !!! 注意事项
    #   必须在导入蓝图之前

    三、初始化

    def create_app():
        app = Flask(__name__)
        app.config.from_object("settings.BaseConfig")
    
        app.register_blueprint(us)
        # Flask-Session 第二步实例化session
        Session(app)
        # 初始化db
        db.init_app(app)
        return app

    四、在配置文件写入配置信息

    class BaseConfig(object):
        # Flask-Session  第三步
        # SESSION_TYPE = 'redis'
        # SESSION_REDIS = Redis(host='192.168.0.94', port='6379')
    
        SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:root1234@127.0.0.1:3306/code_record?charset=utf8"
        SQLALCHEMY_POOL_SIZE = 10
        SQLALCHEMY_MAX_OVERFLOW = 5
    
        # SQLALCHEMY_TRACK_MODIFICATIONS = False
        pass

    五、创建model

    from sqlalchemy import Column, Integer, String
    from flask_demo import db
    
    
    class Users(db.Model):
        __tablename__ = 'users'
    
        id = Column(Integer, primary_key=True)
        name = Column(String(32), index=True, nullable=False)

    六、生成表(需要使用app上下文)

    """
    Web运行时,flask程序运行起来,用户通过浏览器访问
    离线脚本,自定义的一个py文件+使用flask中定义好的功能
    """
    from flask_demo import db, create_app
    from flask_demo.models import *
    # 一定要导入models 否则找不到表创建不出来
    app = create_app()
    app_ctx = app.app_context()
    
    with app_ctx:
        db.create_all()  # 创建
        # db.drop_all()  # 删除
        data = db.session.query(models.Users).all  # 查询
        print(data)

    七、基于ORM对数据库操作

    from flask import Blueprint
    from flask_demo import db
    from flask_demo.models import Users
    
    us = Blueprint("us", __name__)
    
    
    @us.route("/index")
    def index():
        # db.session.add(Users(name="peng"))
        # db.session.commit()
        # db.session.remove()
        ret = db.session.query(Users).all()
        print(ret)
        db.session.remove()
        return "INDEX~~"

    Flask-Script

    一、下载安装

    pip3 install flask-script

    二、增加的功能 runserver

    from flask_demo import create_app
    from flask_script import Manager
    
    app = create_app()
    manager = Manager(app)
    
    if __name__ == '__main__':
        # app.run()
        manager.run()
    # 启动命令变成
    # python3 manager.py runserver -h 127.0.0.1 -p 8000
    # Running on http://127.0.0.1:8000/ (Press CTRL+C to quit)

    三、自定义命令

    from flask_demo import create_app
    from flask_script import Manager
    
    app = create_app()
    manager = Manager(app)
    
    
    # 位置传参
    @manager.command
    def custom(arg):
        """
        自定义命令
        python manage.py custom 123
        """
        print(arg)
        
        
    # 关键字传参
    @manager.option('-n', '--name', dest='name')
    @manager.option('-u', '--url', dest='url')
    def cmd(name, url):
        """
        自定义命令
        执行: python manage.py  cmd -n peng -u http://www.peng104.xyz
        """
        print(name, url)
    
    
    if __name__ == '__main__':
        # app.run()
        manager.run()

    Flask-migrate

    一、下载安装

    pip3 install flask-migrate

    二、增加的命令  

    注意: 依赖flask-script 

    from flask_demo import create_app, db
    from flask_demo.models import *
    from flask_script import Manager
    from flask_migrate import Migrate, MigrateCommand
    
    app = create_app()
    manager = Manager(app)
    Migrate(app, db)
    
    """
    # 数据库迁移命名
    # 依赖 flask-script
    python manage.py db init # 初始化
    python manage.py db migrate # makemigrations
    python manage.py db upgrade # migrate
    """
    manager.add_command("db", MigrateCommand)
    
    if __name__ == '__main__':
        # app.run()
        manager.run()

    wtforms

    类比我们django的Form组件~

    Form组件的主要应用是~帮助我们自动生成HTML,以及做表单数据的验证~

    用法跟Form组件大同小异~

    一、下载安装

    pip3 install wtforms

    二、自动生成HTML

    第一步 生成一个Form类

    第二步 实例化这个Form类,把这个实例化对象当成参数传递给前端

    from wtforms import Form, widgets, validators
    from wtforms.fields import simple
    class MyForm(Form):
        name = simple.StringField(
            label="用户名",
            render_kw={"placeholder": "请输入用户名"},
            widget=widgets.TextArea(),
            default="wenerxin"
        )
        pwd = simple.PasswordField()
    
    
    @ac.route("/login", methods=["GET", "POST"])
    def login():
        if request.method == "GET":
            form = MyForm(data={"name": "xin"})
            return render_template("login.html", form=form)
    视图页面
    <!--html页面-->
    <form action="" novalidate>
        用户名: {{form.name}}
        密码: {{form.pwd}}
        <button type="submit">提交</button>
    
    </form>
    <!--循环出来的页面-->
    <form action="">
        {% for field in form %}
            {{field.label}}: {{field}}
    
        {% endfor %}
        <button type="submit">提交</button>
    
    </form>
    html页面

    三、验证

    第一步  在Form类中增加验证信息

    第二步 在视图中做数据的校验 并且页面展示错误信息

    class MyForm(Form):
        name = simple.StringField(
            label="用户名",
            render_kw={"placeholder": "请输入用户名"},
            # widget=widgets.TextArea(),
            validators=[
                validators.DataRequired(message="用户名不能为空"),
                validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d')
            ],
            # default="wenerxin",  # 设置默认值
            # render_kw={"class":"form-control"}  #设置属性
        )
        pwd = simple.PasswordField(
            label="密码",
            widget=widgets.PasswordInput(),
            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个特殊字符')
            ]
        )
    
    
    @ac.route("/login", methods=["GET", "POST"])
    def login():
        if request.method == "GET":
            form = MyForm(data={"name": "wen"})
            return render_template("login.html", form=form)
        form = MyForm(formdata=request.form)
        if form.validate():
            print(form.data)
        else:
            return render_template("login.html", form=form)
        return "LOGIN~~"
    视图页面
    <form action="" method="post" novalidate>
        {% for field in form %}
            {{field.label}}: {{field}} {{field.errors[0]}}
    
        {% endfor %}
        <button type="submit">提交</button>
    
    </form>
    循环出来的页面

    四、拓展字段

    以用户注册为例,输入用户名,密码,重复密码,性别和爱好。

    class RegisterForm(Form):
        name = simple.StringField(
            label='用户名',
            validators=[
                validators.DataRequired()
            ],
            widget=widgets.TextInput(),
            # render_kw={'class': 'form-control'},
            default='gaoxin'
        )
    
        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(  # 这里用的是html5.EmaliField
            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  # 限制是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):
            '''
            重写__init__方法
            这里的self是一个RefisterForm对象
            '''
            super(RegisterForm, self).__init__(*args, **kwargs)  # 继承父类init方法
            # 从数据库获取数据 做到实时更新
            # 把RegisterForm这个类里面的favor重新赋值
            self.favor.choices = ((1, '篮球'), (2, '足球'), (3, '羽毛球'))
    
    
    @ac.route('/register', methods=['GET', 'POST'])
    def register():
        if request.method == 'GET':
            form = RegisterForm(data={'gender': 1})  #默认值是1
            return render_template('register.html', form=form)
        else:
            form = RegisterForm(formdata=request.form)
            if form.validate():  # 判断是否验证成功
                return "注册成功"
            else:
                print(form.errors)
                return render_template('register.html', form=form)    
    视图
    <!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 item in form %}
        <p>{{item.label}}: {{item}} {{item.errors[0] }}</p>
        {% endfor %}
        <input type="submit" value="提交">
    </form>
    </body>
    </html>
    register.html

    注意:选项字段需要去数据库取数据,还有就是从数据库取数据的实时更新

    信号 blinker

    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, 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()
  • 相关阅读:
    http请求的GET和POST请求:查询和新增(server.php)
    http请求的GET和POST请求:查询和新增(ajax)
    shell中$(( )) 与 $( ) 还有${ }的区别
    linux查看操作系统版本信息
    Linux useradd 与 adduser的区别, /sbin/nologin 与 /bin/bash
    红帽触摸屏屏幕180旋转
    Sed命令n,N,d,D,p,P,h,H,g,G,x解析3
    sed命令
    sed高级用法:模式空间(pattern space)和保持空间(hold space)
    sed的模式空间和保持空间
  • 原文地址:https://www.cnblogs.com/peng104/p/10223059.html
Copyright © 2011-2022 走看看