• ORM框架


    1 面向对象

        函数编程是有很多局部变量和函数的, 这样会有很多重复
        形成的面向对象思想
        面向对象思想的使用条件:
            当一类函数共用同样的参数的时候, 面向对象会把数据和逻辑组合在一起
        常用的面向对象特殊方法
            __init__(): 初始化
            __call__(): 对象后面加括号执行
            __dict__: 含有的数据
            对象[key]: __getitem__(self, key)
            对象[key] = 值: __setitem__(self, key, value)
            del 对象[key]: __delitem__(self)

    2 ORM框架

        主流的Python中的ORM框架是: SQLAlchemy
        作用:
            1) 提供简单的规则
            2) 自动转换成SQL语句
        分类
            1) db first: [手动]数据库+表 -->ORM --> [自动]类
            2) code first: [手动]数据库+类 -->ORM --> [自动]表

    3 SQLAlchemy的使用

    3.1 创建数据库

        
        1) 新建连接
    from sqlalchemy import create_engine
    engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/t1", max_overflow=5)
      分别是格式是: 数据库类型+连接API://用户名:密码@IP地址/数据库名
      max_cverflow表示最大连接数, 是通过ConnectionPooling来实现连接池的
        2) 创建表对应的类
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String, UniqueConstraint, Index
    Base = declarative_base()
    class UserType(Base):
        __tablename__ = 'usertype'
        id = Column(Integer, primary_key=True, autoincrement=True)
        name = Column(String(32), nullable=True, default='NoName', index=True)
    class Users(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True, autoincrement=True)
        name = Column(String(32), nullable=True, default='NoName', index=True)
        extra = Column(String(16), unique=True)
        user_type_id = Column(Integer, ForeignKey("usertype.id"))
        __table_args__ = (
            UniqueConstraint('id', 'name', name='uix_id_name'),
            Index('ix_id_name', 'name', 'extra'),
        )
            其中要保证, 该类继承自declarative_base()
            创建以列是使用Conlum, 里面可以传入数据类型和约束条件primary_key, autoincrement等
            可以创建外键, 注意外键的写法是首字母F大写, 和别的不一样
            特殊变量__tablename__记录表名
            特殊变量__table_args__记录表级约束条件, 其中的诸如Index()有多个参数, 第一个参数默认是约束条件的名字, 如果不放在第一个参数上, 在后面就需要指定name=
        3) 创建或者删除数据库
    Base.metadata.create_all(engine)
    Base.metadata.drop_all(engine)
        注意创建或者删除不是随意的, 是找到继承自Base的类进行相应的创建

    3.2 记录的操作

       1) 基本框架
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/orm", max_overflow=5)
    Session = sessionmaker(bind=engine)
    session = Session()
    # 数据库操作
    session.commit()
    session.close()
        通过bind创建一个会话, 通过这个会话得到一个会话对象, 经过一系列的操作之后, 需要提交并关闭会话
        2) 插入数据
    obj1 = UserType(title='普通用户')
    session.add(obj1)
    objs =[
      UserType(title='超级用户'),
      UserType(title='白金用户'),
      UserType(title='黑金用户'),
    ]
    session.add_all(objs)
        有两种插入数据的方式, 单条插入的时候用add()方法插入一个表对象; 多条插入的时候是使用add_all()传入一个list, 里面的元素是一个个表对象
        3) 生成SQL语句
        可以通过query()函数来生成一个SQL语句
        里面的参数传入数据, 若是一个表类名, 表示查询整个表
    session.query(UserType)
    #SELECT usertype.id AS usertype_id, usertype.title AS usertype_title FROM usertype
        可以在后面加上函数all()来执行得到结果
    session.query(UserType).all()
    # [<__main__.UserType object at 0x000000000383D630>, 
    # <__main__.UserType object at 0x000000000383D668>, 
    # <__main__.UserType object at 0x000000000383D6D8>]
        可以遍历结果得到每一行, 可以用数组的方式获得值, 亦可以用.的方法.属性
    user_type_list = session.query(UserType).all()
    for row in user_type_list:
        print(row[0],row.title)
        使用filter()可以增加查询条件, 相当于where
    session.query(UserType.id,UserType.title).filter(UserType.id > 2)
        删除数据需要先使用query查询到在使用delete()
    session.query(UserType.id,UserType.title).filter(UserType.id > 2).delete()
        修改数据的使用update()
    session.query(UserType.id,UserType.title).filter(UserType.id > 0).update({"title" : "黑金"})
    session.query(UserType.id,UserType.title).filter(UserType.id > 0).update({UserType.title: UserType.title + "x"}, synchronize_session=False)
    session.query(UserType.id,UserType.title).filter(UserType.id > 0).update({"num": Users.num + 1}, synchronize_session="evaluate")
        其中synchronize_session=False与字符串处理的时候联合使用的
        synchronize_session="evaluate"是处理数字类型的时候联合使用的

    3.3 进阶的SQL语句

        1) 条件
    ret = session.query(Users).filter_by(name='alex').all()
    ret = session.query(Users).filter(Users.id > 1, Users.name == 'eric').all()
    # filter中的条件用逗号隔开, 默认是AND
    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()
    # not in的写法
    ret = session.query(Users).filter(Users.id.in_(session.query(Users.id).filter_by(name='eric'))).all()
    # 之前默认的条件叠加的and, 可以把条件该为or, 需要导入包
    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()
    # 谁的方法, 里面的值就是按照什么类型拼接
        2) 通配符
    ret = session.query(Users).filter(Users.name.like('e%')).all()
    ret = session.query(Users).filter(~Users.name.like('e%')).all()
        3) limit限制
    ret = session.query(Users)[1:2]
        4) 排序
    ret = session.query(Users).order_by(Users.name.desc()).all()
    ret = session.query(Users).order_by(Users.name.desc(),Users.id.asc()).all()
        5) 分组
    ret = session.query(Users).group_by(Users.extra).all()
    from sqlalchemy.sql import func
    # 导入func才能够使用聚合函数
    ret = session.query(
    func.max(Users.id),
    func.sum(Users.id),
    func.min(Users.id)).group_by(Users.name).all()
    # 可以使用having语句
    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()
        6) 联结
    # 笛卡尔积 相当于:select * from user,usertype;
    ret = session.query(Users,UserType)
    # 內联结 相当于:select * from user,usertype whre user.usertype_id = usertype.id
    ret = session.query(Users,UserType).filter(Users.usertype_id==UserType.id)
    # 內联结, 默认会查找外键, 通过外键来联结
    ret = session.query(Users).join(UserType)
    # 左联结
    ret = session.query(Users).join(UserType,isouter=True)
        7) 组合
    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()
        8) 子查询
    # 子查询 等同效果:select * from (select * from tb) as B
    q1 = session.query(UserType).filter(UserType.id >0).subquery()
    ret = session.query(q1).all()
        9) 记录子查询
    # 查询语句 等效于:
    # select
    # id ,
    # (select * from users where users.user_type_id=usertype.id)
    # from usertype;
    ret = session.query(UserType.id,session.query(Users).filter(Users.user_type_id==UserType.id).as_scalar())
        如果此时用子查询subquery()会得到一个笛卡尔积, 因为subquery()会返回一个临时表
        使用as_scalar()相当于得到一个相应的查询语句, 并且用()包裹起来

    3.4 关系表

        数据库中常常用到有外键的表的联结操作
        在SQLAlchemy中有一个便捷的操作可以使得不用手动联结也能在查询中使用
        也就是使用relationship
        在带有外键的类中添加
    关系名A = relationship("关联的表的类名",backref='回调名B')
        这样就可以在查询该表的时候获得关系名A, 通过关系名A点的方式得到对应的关联表的数据
        同时查询对应的关联表, 就可以得到回调名B, 通过回调名B点的方式得到表的数据
     
     
  • 相关阅读:
    Spring boot mvn
    软考
    java
    webserver代理生成本地类的两种方式
    行转列语句,记录一下
    React.PureComponent浅比较理解
    关于职业规划和职场规则以及未来发展发方向
    程序员的一天
    代码commit规范
    element UI 使用总结
  • 原文地址:https://www.cnblogs.com/weihuchao/p/7007003.html
Copyright © 2020-2023  润新知