• FlaskWeb开发从入门到放弃(二)


    第5章 章节五

    • 01 内容概要

    • 02 内容回顾

    • 03 面向对象相关补充:metaclass(一)

    • 04 面向对象相关补充:metaclass(二)

    • 05 WTforms实例化流程分析(一)

    • 06 WTforms实例化流程分析(二)

    • 07 拓展:相关面试题

    • 08 ORM框架概念

    • 09 SQLAlchemy框架快速使用

    • 10 SQLAlchemy框架组件使用

    • 11 SQLAlchemy执行原生SQL

    • 12 上述内容总结

    • 13 SQLAlchemy创建表结构

    • 14 SQLAlchemy实现基本增删改查(一)

    • 15 SQLAlchemy实现基本增删改查(二)

    • 16 SQLAlchemy小练习

    • 17 SQLAlchemy常见操作

    • 18 上述内容总结

    • 19 homework

    第6章 章节六

    • 01 内容概要

    • 02 内容回顾

    • 03 WTforms组件验证流程

    • 04 SQLAlchemy操作补充

    • 05 homework

    第7章 章节七

    • 01 内容概要

    • 02 内容回顾

    • 03 Flask-script组件

    • 04 FLask-SQLAlchemy组件应用(一)

    • 05 Flask-SQLAlchemy组件应用(二)

    • 06 Flask-SQLAlchemy组件应用(三)

    • 07 Flask-SQLAlchemy组件应用总结

    • 08 SQLAlchemy创建session的两种方式

    • 09 Flask-Migrate组件

    • 10 Flask自定义拓展

    • 11 Flask多app应用

    • 12 Flask信号blinker

    • 13 Flask信号和before_request的区别

    • 14 内容总结和作业

    第5章 章节五

    01 内容概要

    1.1 面向对象相关;

    • _mro__;
    • metaclass;

    1.2 WTforms;

    1.3 SQLALchemy(Flask中的一个ORM框架);

    1.4 SQLALchemy/flask-sqlalchemy;

    1.5 flask其他;

    • flask-script;
    • flask-migrate;
    • 多app应用;
    • 离线脚本;

    02 内容回顾

    2.1 Flask和Django的区别;

    1:重量级web框架,功能齐全,提供一站式解决的思路,能让开发者不用在选择应用上花费大量时间;
    2:自带ORM(Object-Relational Mapping 对象关联映射)和模板引擎,支持JinJa等非官方模板引擎,灵活度不高;
    3:自带ORM使Django和关系型数据库耦合度过高,如果要使用非关系型数据库,需要使用第三方库;
    4:自带数据库管理app;
    5:成熟、稳定、开发效率高、相对于Flask,Django的整体封闭性比较好,适合做企业级网站的开发;
    6:python web框架的先驱,第三方库丰富;
    7:上手容易,开发文档详细、完善、资料丰富;
    
    
    
    1:轻量级web框架,只有一个内核,默认依赖两个外部库:Jinja2 模板引擎和 Werkzeug WSGI 工具集,自由,灵活,可扩展性强,开发者可以根据需求自己造轮子;
    2:适用于做小型网站以及web服务的API,开发大型网站无压力,架构需自行设计;
    3:与关系型数据库结合不弱于Django,而与非关系型数据库的结合远远优于Django;

    2.2 Flask的上下文管理是如何实现的?

    http://www.cnblogs.com/zhaopanpan/articles/9457343.html

    问题一:flask和django的区别:
      对于django来说,内部组件特别多,自身功能强大,有点大而全,而flask,内置组件很少,但是它的第三方组件很多,扩展性强,有点短小精悍,而它们之间也有相似之处,
      因为它们两个框架都没有写sockte,都是基于wsgi协议做的,在此之外,flask框架中的上下文管理较为耀眼。
    
      
      相同点:它们两个框架都没有写sockte,都是基于wsgi协议做的
      请求相关数据传递的方式不同:django:通过传递request参数取值
                    flask:见问题二
               组件不同:django组件多
                    flask组件少,第三方组件丰富
    
    问题1.1: flask上下文管理:
      简单来说,falsk上下文管理可以分为三个阶段:
            1、请求进来时,将请求相关的数据放入上下问管理中
            2、在视图函数中,要去上下文管理中取值
            3、请求响应,要将上下文管理中的数据清除
      
      详细点来说:
            1、请求刚进来,将request,session封装在RequestContext类中,app,g封装在AppContext类中,并通过LocalStack将requestcontext和appcontext放入Local类中
            2、视图函数中,通过localproxy--->偏函数--->localstack--->local取值
            3、请求相应时,先执行save.session()再各自执行pop(),将local中的数据清除
            
    
    问题1.2  flask第三方组件
      flask:
          -flask-session    默认放入cookie,可以放入redis
          -flask-redis
          -flask-migrate
          -flask-script
          -blinker  信号
       公共: DBUtils      数据库连接池
          wtforms       表单验证+生成HTML标签
          sqlalchemy
      自定义:Auth   参考falsk-login
    
    问题二:Flask中的session是什么时候创建,什么时候销毁的?
      当请求进来时,会将requset和session封装为一个RequestContext对象,通过LocalStack将RequestContext放入到Local对象中,因为
    请求第一次来session是空值,所以执行open_session,给session(uuid4())赋值,再通过视图函数处理,请求响应时执行save.session,将签名session写入cookie中,再讲Local中的数值pop掉。
    
    问题三:flask中一共有几个LocalStack和Local对象
      两个LocalStack,两个Local
      request、session共同用一个LocalStack和Local
      g、app共同用一个Localstack和Local
    
    问题四: 为什么把请求放到RequestContext中:
       因为request和session都是在视图中操作频繁的数据,也是用户请求需要用的数据,将request和session封装在RequestContext中top,pop一次就可以完成,而单独不封装在一起就会多次操作,
    
        ctx = RequestContext(request,session)
    
    问题五:local作用
        -保存    请求上下文对象和app上下文对象
    
         -localstack的源码与threading.local(线程处理)作用相似,不同之处是Local是通过greenlet(协程)获取唯一标识,粒度更细
          
     问题六:Localstack作用
        2、将local对象中的数据维护成一个栈【ctx,ctx】(先进后出)
             {
                “协程或线程的唯一标识”: { stack:[ctx,ctx,ctx,] }
             }
        
    
    为什么维护成一个栈?
        当是web应用时:不管是单线程还是多线程,栈中只有一个数据
       - 服务端单线程:
            {
                111:{stack: [ctx, ]}
            }
       - 服务端多线程:
            {
                111:{stack: [ctx, ]}
                112:{stack: [ctx, ]}
            }
    离线脚本:可以在栈中放入多个数据
    with app01.app_context():
                          print(current_app)
                          with app02.app_context():
                                print(current_app)
                          print(current_app)
    
    
     
     问题七:什么是g?
        g 相当于一次请求的全局变量,当请求进来时将g和current_app封装为一个APPContext类,在通过LocalStack将Appcontext放入Local中,取值时通过偏函数,LocalStack、loca l中取值,响应时将local中的g数据删除:
     问题八:怎么获取Session/g/current_app/request
        通过 、偏函数(lookup_req_object)、Localstack、Local取值
      问题九: 技术点:
              - 反射 (LocalProxy())
              - 面向对象,封装:RequestContext
      - 线程(threading.local)
              - 笔试:自己写一个类+列表 实现栈。(LocalStack)
    问题十:python基本哪些内容比较重要:
    1、反射
      -CBV
      -django配置文件
      -wtforms中的Form()示例化中 将"_fields中的数据封装到From类中"
    2、装饰器 (迭代器,生成器)
      -flask:路由、装饰器
    
      -认证
      -csrf
    3、面向对象
      -继承、封装、多态(简单描述)
     -双下划线:
        __mro__ wtform中 FormMeta中继承类的优先级
         __dict__    
        __new__ ,实例化但是没有给当前对象
                                            wtforms,字段实例化时返回:不是StringField,而是UnboundField
           rest frawork many=Turn  中的序列化
         __call__
                                           flask 请求的入口app.run()
                                            字段生成标签时:字段.__str__ => 字段.__call__ => 插件.__call__
        
           __iter__ 循环对象是,自定义__iter__
    
    
            wtforms中BaseForm中循环所有字段时定义了__iter__
         metaclass
                                        - 作用:用于指定当前类使用哪个类来创建
                                        - 场景:在类创建之前定制操作
                                                示例:wtforms中,对字段进行排序。

    2.3 Local的作用:

    • 用于保存——请求上下文对象和app上下文对象;
    • 做到“线程”间的数据隔离;

    2.4 LocalStack作用?

    • 将Local中保存的数据维护成一个栈(弹夹,后进先出);

    2.5 Flask的内置组件;

    • 配置
    • 路由
    • 视图
    • 模板
    • session
    • 蓝图
    • 闪现
    • 装饰器
    • 中间件

    2.6 第三方组件;

    • flask-session;私有,将原来保存在Cookies中的session数据保存在redis或者memcache中;
    • DBUtils;公共,数据库连接池,维护数据库连接;
    • WTforms;公共,用于做表单验证,生成html标签;

    03 面向对象相关补充:metaclass(一)

    3.1 面向对象相关-__mro__;

    04 面向对象相关补充:metaclass(二)

    4.1 metaclass的相关说明;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-21 16:31
    # File    : 3.metaclass.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    # 创建类的两种方式;
    
    # 方式一:
    class Foo(object):
        CITY = 'BJ'
    
        def func(self, x):
            return x + 1
    
    
    # 方式二:
    
    def func(self, x):
        return x + 1
    
    
    # Foo1 = type('Foo1', (object,), {'CITY': 'BJ', 'func': func})
    
    
    # 另外一种形式:
    Foo2 = type('Foo', (object,), {'CITY': 'BJ', 'func': lambda self, x: x + 1})
    
    
    # 2、类由自定义type创建;
    class Foo3(object, metaclass=type):  # 当前类由type类创建;
        # __metaclass__ = type# Python2的创建方式;
        CITY = 'BJ'
    
        def func(self, x):
            return x + 1
    
    
    class MyType(type):
        def __init__(self, *args, **kwargs):
            print('创建类之前')
            super(MyType, self).__init__(*args, **kwargs)
            print('创建类之后')
    
    
    class Foo4(object, metaclass=MyType):
        CITY = 'BJ'
    
        def func(self, x):
            return x + 1
    
    
    print(Foo4)
    """
    1、类由type创建,metaclass可以指定当前类由哪一个类创建;
    """
    
    
    class MyType1(type):
        def __init__(self, *args, **kwargs):
            print('创建类之前')
            super(MyType1, self).__init__(*args, **kwargs)
            print('创建类之后')
    
    
    class Foo1(object, metaclass=MyType1):
        CITY = 'BJ'
    
        def func(self, x):
            return x + 1
    
    
    class Bar(Foo):
        pass
    
    
    """
    小结:
    1、默认类由type实例化创建;
    2、某个类指定metaclass = MyType,那么当前类的所有派生类都由于MyType创建;
    3、实例化对象:
        -type.__init__
        -type.__call__
        -类名.__new__
        -类名.__init__
    """

    05 WTForms实例化流程分析(一)

    5.1 WTForms的实例化流程; 

    # 源码流程
        1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中; meta类读取到cls._wtforms_meta中
        2. 执行构造方法
            
            a. 循环cls._unbound_fields中的字段,并执行字段的bind方法,然后将返回值添加到 self._fields[name] 中。
                即:
                    _fields = {
                        name: wtforms.fields.core.StringField(),
                    }
                    
                PS:由于字段中的__new__方法,实例化时:name = simple.StringField(label='用户名'),创建的是UnboundField(cls, *args, **kwargs),当执行完bind之后,才变成执行 wtforms.fields.core.StringField()
            
            b. 循环_fields,为对象设置属性
                for name, field in iteritems(self._fields):
                    # Set all the fields to attributes so that they obscure the class
                    # attributes with the same names.
                    setattr(self, name, field)
            c. 执行process,为字段设置默认值:self.process(formdata, obj, data=data, **kwargs)
                优先级:obj,data,formdata;
                
                再循环执行每个字段的process方法,为每个字段设置值:
                for name, field, in iteritems(self._fields):
                    if obj is not None and hasattr(obj, name):
                        field.process(formdata, getattr(obj, name))
                    elif name in kwargs:
                        field.process(formdata, kwargs[name])
                    else:
                        field.process(formdata)
                
                执行每个字段的process方法,为字段的data和字段的raw_data赋值
                def process(self, formdata, data=unset_value):
                    self.process_errors = []
                    if data is unset_value:
                        try:
                            data = self.default()
                        except TypeError:
                            data = self.default
            
                    self.object_data = data
            
                    try:
                        self.process_data(data)
                    except ValueError as e:
                        self.process_errors.append(e.args[0])
            
                    if formdata:
                        try:
                            if self.name in formdata:
                                self.raw_data = formdata.getlist(self.name)
                            else:
                                self.raw_data = []
                            self.process_formdata(self.raw_data)
                        except ValueError as e:
                            self.process_errors.append(e.args[0])
            
                    try:
                        for filter in self.filters:
                            self.data = filter(self.data)
                    except ValueError as e:
                        self.process_errors.append(e.args[0])
                    
            d. 页面上执行print(form.name) 时,打印标签
                
                因为执行了:
                    字段的 __str__ 方法
                    字符的 __call__ 方法
                    self.meta.render_field(self, kwargs)
                        def render_field(self, field, render_kw):
                            other_kw = getattr(field, 'render_kw', None)
                            if other_kw is not None:
                                render_kw = dict(other_kw, **render_kw)
                            return field.widget(field, **render_kw)
                    执行字段的插件对象的 __call__ 方法,返回标签字符串
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    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 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()
    
    app.py

    06 WTforms实例化流程分析(二)

    6.1 WTForms实例化流程分析;

    a. 执行form的validate方法,获取钩子方法
                def validate(self):
                    extra = {}
                    for name in self._fields:
                        inline = getattr(self.__class__, 'validate_%s' % name, None)
                        if inline is not None:
                            extra[name] = [inline]
            
                    return super(Form, self).validate(extra)
            b. 循环每一个字段,执行字段的 validate 方法进行校验(参数传递了钩子函数)
                def validate(self, extra_validators=None):
                    self._errors = None
                    success = True
                    for name, field in iteritems(self._fields):
                        if extra_validators is not None and name in extra_validators:
                            extra = extra_validators[name]
                        else:
                            extra = tuple()
                        if not field.validate(self, extra):
                            success = False
                    return success
            c. 每个字段进行验证时候
                字段的pre_validate 【预留的扩展】
                字段的_run_validation_chain,对正则和字段的钩子函数进行校验
                字段的post_validate【预留的扩展】

    07 拓展:相关面试题

    7.1 Python基础部分哪些比较重要?

    • 反射——CBV、Django的配置文件、WTForms;
    • 装饰器——Flask路由、认证、CRSF
    • 生成器、迭代器
    • 面向对象——继承、封装和多态;特殊的功能:双下划线方法(__mro__、__dict__、__new__、__call__、__iter__)以及metaclass;

    08 ORM框架概念

    8.1 什么是ORM框架?

    关系-对象-映射(Object-Object Relational Mapping);

    当有了对应关系后,不再需要编写SQL语句,取而代之是操作:类、对象;

    8.2 ORM和原生SQL的优缺点?

      8.2.1 ORM;

    • 快速开发
    • 性能差

      8.2.2 SQL;

    • 性能好
    • 开发速度慢

      8.2.3 DB First(已经使用原生SQL开发,根据数据库的表生成类);

      8.2.4 Code First(ORM是CodeFirst,根据类创建数据表);

    • python3 manage.py inspect

      8.2.5 ORM是如何实现的?内置解析器实现;通过对象和类转化成字符换;

    09 SQLAlchemy框架快速使用

    9.1 SQLAlchemy,是一个基于Python实现的ORM框架;

    9.2 SQLAlchemy的快速使用;

    ORM.py;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 09:54
    # File    : 1.ORM.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    
    ""
    """
    SQLAlchemy插入数据操作;
    """
    import models
    #from sqlalchemy.ext.declarative import declarative_base
    #from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
    from sqlalchemy.orm import sessionmaker, relationship
    from sqlalchemy import create_engine
    
    engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/flask_session", max_overflow=5)
    Session = sessionmaker(bind=engine)
    session = Session()
    
    obj1 = models.Users(name="cuixiaozhao", extra="cxz")
    obj2 = models.Users(name="cuixiaozhao", extra="cxz")
    
    
    session.add(obj1)
    session.add(obj2)
    session.commit()

    models.py;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 09:54
    # File    : models.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    ""
    """
    1、安装pip3 install sqlalchemy ;
    2、依赖于pymysql进行数据库连接;
    3、并不支持修改表结构,仅支持在数据库修改字段后,再重新在此处修改;
    """
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String, UniqueConstraint, Index
    from sqlalchemy import create_engine
    
    Base = declarative_base()
    
    
    # 创建数据表;
    class Users(Base):
        __tablename__ = "users"
        id = Column(Integer, primary_key=True, autoincrement=True)
        name = Column(String(32))
        extra = Column(String(16))
    
        # __table_args = (
        #     UniqueConstraint('id', 'name', name='uix_id_name'),
        #     Index('ix_id_name', 'name', 'extra')
        # )
    
    
    # 数据库连接相关;
    # engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com/flask_session?charset=utf8")
    # Base.metadata.create_all(engine)
    # 删除表;
    # Base.metadata.drop_all(engine)
    
    # 向表中插入数据;
    def init_db():
        # 数据库连接相关;    
        engine = create_engine("mysql+pymysql://root:Tqtl913421411!@%*)@123.321.com:3306/flask_session?charset=utf8")
        # 创建表;
        Base.metadata.create_all(engine)
    
    
    def drop_db():
        # 数据库连接相关;
        engine = create_engine("mysql+pymysql://root:Tqtl911!@%*4321432)@123.321.com:3306/flask_session?charset=utf8")
        # 删除表;
        Base.metadata.drop_all(engine)
    
    
    if __name__ == '__main__':
        init_db()
        # drop_db()

    10 SQLAlchemy框架组件使用

    10.1 SQLAlchemy框架组件使用;

    SQLAlchemy本身无法操作数据库,其必须以来pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:

    MySQL-Python
        mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
       
    pymysql
        mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
       
    MySQL-Connector
        mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
       
    cx_Oracle
        oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
       
    更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html

    11 SQLAlchemy执行原生SQL

    11.1 SQLAlchemy执行原生SQL语句操作;

    • 基于SQLAlchemy写原生SQL(优势在于自带数据库连接池);
    • 基于SQLAlchemy写ORM;
    • DBUtils+pymysql创建连接池;
    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 11:05
    # File    : 3.执行原生SQL.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    from sqlalchemy import create_engine
    
    engine = create_engine("mysql+pymysql://root:@flask_session123456mysql.cuixiaozhao.com:3306/", max_overflow=5)
    
    # 执行SQL
    cur = engine.execute(
        "INSERT INTO hosts (host, color_id) VALUES ('1.1.1.22', 3)"
    )
    
    # 新插入行自增ID
    cur.lastrowid
    
    # 执行SQL
    cur = engine.execute(
        "INSERT INTO hosts (host, color_id) VALUES(%s, %s)", [('1.1.1.22', 3), ('1.1.1.221', 3), ]
    )
    
    # 执行SQL
    cur = engine.execute(
        "INSERT INTO hosts (host, color_id) VALUES (%(host)s, %(color_id)s)",
        host='1.1.1.99', color_id=3
    )
    
    # 执行SQL
    cur = engine.execute('select * from hosts')
    # 获取第一行数据
    cur.fetchone()
    # 获取第n行数据
    cur.fetchmany(3)
    # 获取所有数据
    cur.fetchall()

    12 上述内容总结

    12.1 基于SQLALchemy实现数据库的增删改查;

    12.2 单表操作;

    12.3 多表操作;

    13 SQLAlchemy创建表结构

    13.1 使用SQLAlchemy;

    • 安装 pip3 install sqlalchemy pymysql

    14 SQLAlchemy实现基本增删改查(一)

    14.1 基于SQLAlchemy实现基本的创建数据表操作;

    增加;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 15:14
    # File    : 2.单表的增加操作.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    import models
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    
    engine = create_engine("mysql+pymysql://fda!fda%*)@mysql.dfa.com:3306/flask_session?charset=utf8")
    xxxx = sessionmaker(bind=engine)
    session = xxxx()
    
    # 单条记录增加
    # obj = models.Classes(name = "全栈1期")
    # session.add(obj)
    
    # 多条记录增加;
    objs = [
        # models.Classes(name = '全栈2期'),
        models.Classes(name='全栈3期'),
        models.Classes(name='全栈4期'),
        models.Classes(name='全栈5期'),
    ]
    session.add_all(objs)
    session.commit()
    session.close()

    查询;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 15:29
    # File    : 3.单表的查询操作.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    import models
    
    engine = create_engine("mysql+pymysql://fdafda!@%*)@fa.fda.com:3306/flask_session?charset=utf8")
    
    maker = sessionmaker(bind=engine)
    session = maker()
    # 查询;
    
    result = session.query(models.Classes).all()
    # print(result)#[<models.Classes object at 0x10dcb2358>, <models.Classes object at 0x10dcb23c8>, <models.Classes object at 0x10dcb2438>, <models.Classes object at 0x10dcb24a8>, <models.Classes object at 0x10dcb2518>]
    for item in result:
        print(item.id, item.name)
    session.commit()
    session.close()

    删除;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 15:33
    # File    : 4.单表的删除操作.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    import models
    
    engine = create_engine("mysql+pymysql://ffdfdaf!@%*)@fda.cuifdasxiaozhao.com:3306/flask_session?charset=utf8")
    maker = sessionmaker(engine)
    
    session = maker()
    #  删除
    result = session.query(models.Classes).filter(models.Classes.id > 13).delete()
    session.commit()
    session.close()

    修改; 

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 15:38
    # File    : 5.单表的修改操作.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    import models
    
    engine = create_engine("mysql+pymysql://root:Tfdasfda1!@%*)@123.45.67.89:3306/flask_session?charset=utf8")
    maker = sessionmaker(engine)
    
    session = maker()
    
    # 更新操作;˚
    session.query(models.Classes).filter(models.Classes.id > 0).update({models.Classes.name: models.Classes.name + "999"},
                                                                       synchronize_session=False)
    # 尾部的参数决定了是进行字符串操作还是数学运算操作;
    session.commit()
    session.close()

    15 SQLAlchemy实现基本增删改查(二) 

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 15:38
    # File    : 5.单表的修改操作.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    import models
    
    engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/flask_session?charset=utf8")
    maker = sessionmaker(engine)
    
    session = maker()
    
    # 更新操作;˚
    session.query(models.Classes).filter(models.Classes.id > 0).update({models.Classes.name: models.Classes.name + "999"},
                                                                       synchronize_session=False)
    # 尾部的参数决定了是进行字符串操作还是数学运算操作;
    session.commit()
    session.close()

    16 SQLAlchemy小练习

    16.1 小练习; 

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 16:15
    # File    : 7.练习.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine, text
    import models
    
    engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/flask_session?charset=utf8")
    
    maker = sessionmaker(bind=engine)
    session = maker()
    obj = models.Student(username='崔晓丝', password='123456', class_id=2)
    session.add(obj)
    
    # 在学生表中找到崔晓丝;
    obj1 = session.query(models.Student).filter(models.Student.username == '崔晓丝').first()
    print(obj1)  # <models.Student object at 0x108762a90>
    
    # 找到所有学生;
    # 1、LOW B查询方式;
    # objs = session.query(models.Student).all()
    # for obj in objs:
    #     cls_obj = session.query(models.Classes).filter(models.Classes.id ==obj.class_id).first()
    #     print(obj.id,obj.username,obj.class_id,cls_obj.name)
    # 2、主动连表操作;
    objs = session.query(models.Student.id, models.Student.username, models.Classes.name).join(models.Classes,                                                                                        isouter=True).all()
    print(objs)
    
    # 3、relationship引入;
    objs2 = session.query(models.Student).all()
    for item in objs2:
        print(item.id,item.username,item.class_id,item.cls.name)
    
    session.commit()
    session.close()
    
    
    # 4、全栈2期所有的学生
    obj3 = session.query(models.Classes).filter(models.Classes.name =="全栈2期999").first()
    
    student_list = obj3.stus
    for i in student_list:
        print(i.id,i.username)
    print("全栈2期所有的学生",student_list) 

    17 SQLAlchemy常见操作

    17.1 SQLAlchemy常见操作;

    • 分组
    • 连表
    • 组合
    • 条件
    • 通配符 
    • 限制
    # 条件
    ret = session.query(Users).filter_by(name='alex').all()
    ret = session.query(Users).filter(Users.id > 1, Users.name == 'eric').all()
    ret = session.query(Users).filter(Users.id.between(1, 3), Users.name == 'eric').all()
    ret = session.query(Users).filter(Users.id.in_([1,3,4])).all()
    ret = session.query(Users).filter(~Users.id.in_([1,3,4])).all()
    ret = session.query(Users).filter(Users.id.in_(session.query(Users.id).filter_by(name='eric'))).all()
    from sqlalchemy import and_, or_
    ret = session.query(Users).filter(and_(Users.id > 3, Users.name == 'eric')).all()
    ret = session.query(Users).filter(or_(Users.id < 2, Users.name == 'eric')).all()
    ret = session.query(Users).filter(
        or_(
            Users.id < 2,
            and_(Users.name == 'eric', Users.id > 3),
            Users.extra != ""
        )).all()
    
    
    # 通配符
    ret = session.query(Users).filter(Users.name.like('e%')).all()
    ret = session.query(Users).filter(~Users.name.like('e%')).all()
    
    # 限制
    ret = session.query(Users)[1:2]
    
    # 排序
    ret = session.query(Users).order_by(Users.name.desc()).all()
    ret = session.query(Users).order_by(Users.name.desc(), Users.id.asc()).all()
    
    # 分组
    from sqlalchemy.sql import func
    
    ret = session.query(Users).group_by(Users.extra).all()
    ret = session.query(
        func.max(Users.id),
        func.sum(Users.id),
        func.min(Users.id)).group_by(Users.name).all()
    
    ret = session.query(
        func.max(Users.id),
        func.sum(Users.id),
        func.min(Users.id)).group_by(Users.name).having(func.min(Users.id) >2).all()
    
    # 连表
    
    ret = session.query(Users, Favor).filter(Users.id == Favor.nid).all()
    
    ret = session.query(Person).join(Favor).all()
    
    ret = session.query(Person).join(Favor, isouter=True).all()
    
    
    # 组合
    q1 = session.query(Users.name).filter(Users.id > 2)
    q2 = session.query(Favor.caption).filter(Favor.nid < 2)
    ret = q1.union(q2).all()
    
    q1 = session.query(Users.name).filter(Users.id > 2)
    q2 = session.query(Favor.caption).filter(Favor.nid < 2)
    ret = q1.union_all(q2).all()
    
    常用操作

    18 上述内容总结

    18.1 表操作;

    18.2 数据进行操作;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: SQLALchemy 
    # Software: PyCharm
    # Time    : 2018-09-22 19:10
    # File    : 1.总结.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    import models
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    
    engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/flask_session?charset=utf8")
    xxxx = sessionmaker(bind=engine)
    session = xxxx()
    
    session.add
    session.add_all()
    session.query(Users).all()
    session.query(Users.id, Users.name).filter(User.name == 'alex')
    session.query(Users.id, Users.name).filter_by(name='alex')
    session.query(Users.id, Users.name).filter_by(name='alex').filter()
    
    session.query(Users.id, Users.name).filter(User.name == 'alex').update({}, 字符串)
    session.query(Users.id, Users.name).filter(User.name == 'alex').update({}, 计算)
    
    session.query(Users.id, Users.name).filter(Users.name == 'alex').delete()

    19 homework

    第6章 章节六

    01 内容概要

    1.1 WTForms验证流程

    1.2 SQLAlchemy下的lrelationship以及子查询;

    02 内容回顾

    2.1 315++面试题准备;

    2.2 谈谈你对Python和其他语言的区别?

    2.3 为什么要学习Python?

    2.4 基本的数据类型-字符串、字典、元组、列表、集合、collections

    2.5 函数:

    -函数的参数传递的是什么?

    -def func(a,b=[]):pass

    -lambda 表达式

    -列表生成式

    -生成器表达式

    -常见的内置函数:map、reduce、filter、zip、instance、type

    2.6 回顾;

    2.6.1 WTForms作用?

    2.6.2 WTForms涉及到的作用点?哪里用到了?

    • metaclass
    • 封装:UnboundField
    • _new__
    • __mro__
    • setattr
    • type(...)

    2.6.3 ORM和原生SQL比较?

    2.6.4 你用过的ORM框架有哪些?Django ORM SQLAlchemy,所有的语言都有ORM;

    2.6.5 DBFirst、CodeFIrst;

    2.6.6 SQLAlchemy自带数据库连接池;

    03 WTforms组件验证流程

    04 SQLAlchemy操作补充

    4.1 relationship帮助我们做跨表操作-增加和查询;

    4.2 子查询;

    05 homework

    5.1 SQLAlchemy中设置表:引擎、编码;

    5.2 Django中的DBFirst示例;

    5.3 在Flask程序中应用SQLAlchemy;

    第7章 章节七

    01 内容概要

    1.1 Flask内容扫尾-Flask目录创建;

    1.2 Flask-script;

    1.3 flask-sqlalchemy;

    1.4 flask-migrate;

    1.5 flask自定义组件;

    1.6 其他-多app应用;

    1.7 离线脚本&信号(blinker,相当于埋点,需要的时候触发执行即可);

    02 内容回顾

    2.1 谈谈你对Python和其他语言的区别?

      2.1.1 编译型和解释性的区别;

      2.1.2 解释型:Python、PHP

      2.1.3 编译型:C 、C++

      2.1.4 混合型:Java

    2.2 为什么要学习Python?

      2.2.1 简单易学;

      2.2.2 生态圈比较强大;

      2.2.3 发展趋势比较好,人工智能、数据分析;

      2.2.4 还有很多...

    2.3 Python中的数据类型?

    • 字符串
    • 字典
    • 元组
    • 列表
    • 集合
    • collections

    2.4 函数

    • 函数参数传递的是什么?
    • def func(a,b=[]):pass
    • lambda 表达式
    • 列表生成式
    • 生成器表达式(for i in range(1))
    • 常见内置函数-map reduce filter zip instance type

    2.5 生成器、迭代器、装饰器以及可迭代对象

    • 迭代器-主要体现__next__方法;
    • 生成器,迭代器的一种,一个函数存在yield关键字,生成器函数,函数执行,才是生成器,场景:range|xrange,redis取值,stark组件;
    • 可迭代对象,一个类的内部实现__iter__方法且返回一个迭代器;WTForms中对form对象进行循环时候,显示form中包含的所有字段;列表、字典、元组;
    • 装饰器,在不改变原函数代码的基础上,在执行前后进行定制操作;flask路由系统,csrf_token,Django内置的登录;flask_before_request,Django的缓存;

    03 Flask-script组件

    3.1 flask-script的作用;

    • python manage.py runserver
    • python manage.py 自定义命令
    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: FullFlask 
    # Software: PyCharm
    # Time    : 2018-09-23 15:51
    # File    : manage.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    from FullFlask import create_app
    from flask_script import Manager
    
    app = create_app()
    manager = Manager(app)
    
    
    @manager.command
    def custom(arg):
        print(arg)
    
    
    @manager.option('-n', '--name', dest='name')
    @manager.option('-u', '--url', dest='url')
    def cmd(name, url):
        """
        自定义命令:
        执行:python manage.py cmd -n cuixiaozhao -u http://cuixiaozhao.com
        执行:python manage.py cmd --name cuixiaozhao --url http://cuixiaozhao.com
        :param name:
        :param url:
        :return:
        """
        print(name, url)
    
    
    if __name__ == '__main__':
        # app.run()
        manager.run()

    04 FLask-SQLAlchemy组件应用(一)

    4.1 基于SQLAlchemy进行查询数据;

    4.2 Flask项目目录结构如下;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: FullFlask 
    # Software: PyCharm
    # Time    : 2018-09-23 15:54
    # File    : accounts.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    
    
    from flask import blueprints
    from FullFlask import models
    
    ac = blueprints.Blueprint('ac', __name__)
    
    
    @ac.route('/login', methods=['GET', 'POST'])
    def login():
        from sqlalchemy.orm import sessionmaker
        from sqlalchemy import create_engine
        engine = create_engine("mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/FullFlask?charset=utf8")
        maker = sessionmaker(bind=engine)
        session = maker()
        result = session.query(models.Users).all()
        session.close()
        print(
            result)  # [<FullFlask.models.Users object at 0x106123c88>, <FullFlask.models.Users object at 0x106123dd8>, <FullFlask.models.Users object at 0x106123a90>, <FullFlask.models.Users object at 0x1061239e8>]
    
        return 'Login it.'

    05 Flask-SQLAlchemy组件应用(二)

    5.1 SQLAlchemy组件应用二;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: FullFlask 
    # Software: PyCharm
    # Time    : 2018-09-23 16:37
    # File    : settings.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    class BaseConfig(object):
        SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:Tqtl911!@%*)@mysql.cuixiaozhao.com:3306/FullFlask?charset=utf8"
        SQLALCHEMY_POOL_SIZE = 5
        SQLALCHEMY_POOL_TIMEOUT = 30
        SQLALCHEMY_POOL_RECYCLE = -1
    
        # 追踪对象的修改并且发送信号;
        SQLALCHEMY_TRACK_MODIFICATIONS = False
    
    
    class ProductionConfig(BaseConfig):
        pass
    
    
    class DevelopmentConfig(BaseConfig):
        pass
    
    
    class TestConfig(BaseConfig):
        pass
    
    
    """
    小结:
    1、flask-sqlalchemy的作用:将SQLAlchemy相关的所有功能都封装到db=flask_sqlalchemy.SQLAlchemy()对象中;
        -创建表;
        class Users( ):
            pass
            
        -操作表;
        db.session
    
    """

    06 Flask-SQLAlchemy组件应用(三)

    6.1 pip3 install flask-sqlalchemy安装;

    6.2 离线脚本的使用;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: FullFlask 
    # Software: PyCharm
    # Time    : 2018-09-23 17:08
    # File    : drop_table.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    ""
    """
    1、Web运行时候,flask程序运行起来,用户通过浏览器访问;
    2、离线脚本,即自定义的一个py文件+使用flask中定义好的功能;
    """
    from FullFlask import db
    from FullFlask import create_app
    from FullFlask import models
    
    app = create_app()
    with app.app_context():
        # db.drop_all()
        # db.create_all()
        data = db.session.query(models.Users).all()
        print(data)

    07 Flask-SQLAlchemy组件应用总结

    7.1 在__init__.py文件中创建db对象;

    7.2 在__init__.py中的create_app函数中让将app传入到app中;

    7.3 写配置文件,将连接字符串定义在配置文件中;

    7.4 定义models.py文件,导入第一步的db;

    7.5 创建数据库表,编写离线脚本:drop_table.py;

    7.6 在视图函数中,使用SQLAlchemy操作数据库;

    08 SQLAlchemy创建session的两种方式

    8.1 两种创建session的方式;

    • 基于scopted_sessionn进行session = scopted_session(maker)创建
    • 基于传统方式创建;
    • PS:flask-session默认使用scopted_session创建,不再担心多线程问题;

    09 Flask-Migrate组件

    9.1 flask-migrate:做数据库迁移,依赖如下包:

    • flask-script
    • flask-sqlalchemy

    9.2 生成数据库迁移命令;

    • python manage.py db init
    • python manage.py db migrate
    • python manage.py db upgrade

    10 Flask自定义拓展

    11 Flask多app应用

    11.1 Flask的多app应用;

    本质就是对URL的分发和处理;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: FullFlask 
    # Software: PyCharm
    # Time    : 2018-09-23 21:32
    # File    : 多app应用.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    
    from flask import Flask
    from werkzeug.wsgi import DispatcherMiddleware
    
    from werkzeug.serving import run_simple
    
    app01 = Flask('app01')
    app02 = Flask('app02')
    
    dm = DispatcherMiddleware(app01, {
        '/app02': app02,
    })
    
    if __name__ == '__main__':
        run_simple('localhost', 5000, dm)

    12 Flask信号blinker

    12.1 汽车赛道举例;

    12.2 pip3 install blinker# 安装信号;

    12.3 常见信号;

    # Core signals.  For usage examples grep the source code or consult
    # the API documentation in docs/api.rst as well as docs/signals.rst
    template_rendered = _signals.signal('template-rendered')
    before_render_template = _signals.signal('before-render-template')
    request_started = _signals.signal('request-started')
    request_finished = _signals.signal('request-finished')
    request_tearing_down = _signals.signal('request-tearing-down')
    got_request_exception = _signals.signal('got-request-exception')
    appcontext_tearing_down = _signals.signal('appcontext-tearing-down')
    appcontext_pushed = _signals.signal('appcontext-pushed')
    appcontext_popped = _signals.signal('appcontext-popped')
    message_flashed = _signals.signal('message-flashed')

    12.4 flask_signals.py;

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    # Project: FullFlask 
    # Software: PyCharm
    # Time    : 2018-09-23 21:48
    # File    : Flask-signal.py
    # Author  : 天晴天朗
    # Email   : tqtl@tqtl.org
    from flask import Flask, signals
    
    app = Flask(__name__)
    
    
    def func1(*args, **kwargs):
        print('触发信号:request_started')
    
    
    def func2(*args, **kwargs):
        print('触发信号:request_started')
    
    
    signals.request_started.connect(func1)
    signals.appcontext_pushed.connect(func2)
    
    
    @app.route('/login')
    def login():
        return 'Login'
    
    
    if __name__ == '__main__':
        app.run()

    13 Flask信号和before_request的区别

    13.1 brefore_request,可以控制请求是否可以继续往后执行;

    13.2 信号,在原来的基础增加额外的操作和值;

    14 内容总结和作业

    14.1 Flask写完了,如何使用Flask做出个项目;

    14.2 代码发布系统,比如RabbitMQ、saltstack、Celery;

    14.3 面试相关:

      14.3.1 手写Flask内置HelloWorld!

      14.3.2 Flask和其他框架的区别?

      14.3.3 Flask内置组件:

    • 配置
    • 路由
    • 视图
    • 模板
    • session
    • 闪现
    • 蓝图
    • 中间件
    • 特殊装饰器

      14.3.4 Flask第三方组件:

    • flask-session——默认session放在签名的cookie中,使用Redis存储session信息;
    • flask-SQLAlchemy;
    • flask-migrate;
    • flask-script;
    • flask-....还有很多! 
    • blinker

      14.3.5 公共组件:

    • WTForms
    • DBUtils
    • SQLAlchemy

      14.3.6 自定义Flask组件:

    • auth,参考flask-login组件

      14.3.7 上下文管理机制:

    • 为什么使用LocalStack对Local对象进行操作?目的是要将Local中的值;

      14.3.8 Flask项目目录维护;

  • 相关阅读:
    MSSQL复制表
    分享职场心得《7》
    分享职场心得《2》
    分享职场心得《3》
    免费收录网站搜索引擎登录入口最新版
    读写分离,读写分离死锁解决方案
    分享职场心得《5》
    分享职场心得《6》
    分享职场心得《1》
    分享职场心得《4》
  • 原文地址:https://www.cnblogs.com/tqtl911/p/9686998.html
Copyright © 2020-2023  润新知