• MySQL—ORM框架,sqlalchemy模块


    武老师博客:ORM框架介绍

    import os
    #1.当一类函数公用同样参数时候,可以转变成类运行 - 分类
    #2.面向对象: 数据和逻辑组合在一起了
    #3. 一类事物共同用有的属性和行为(方法)
    
    
    #因此 表其实可以写成一个类
    #双下方法item 和 call  必须要背会:
    
    class Userinfo:
        def __init__(self,id,name):
            self.id = id
            self.name = name
        def show(self):
            print('in the show')
    
        def __call__(self, *args, **kwargs):
            print('你在调用call双下方法哦')
    
        def __getitem__(self, item):
            return self.__dict__[item]
    
        def __setitem__(self,key,value):
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            del self.__dict__[key]
    
    user1 = Userinfo(1,'gkx')  #类似表第一行
    
    user1()
    user1['age'] = 22
    print(user1.__dict__)
    print(user1['id'])
    # del user1['age']  #调用 __delitem__ 方法
    del user1.age  #原生方法
    print(user1.__dict__)
    面向对象复习
    #ORM : object relational mapper
    #1.ORM框架: ORM-->关系对象映射 : SQLAlchemy:code first,默认没有db first,想有,要装第三方工具
        #作用
            #1.提供简单的规则
            #2.自动转换成sql语句
    
        #两类
            # DB first / code first 所有的ORM都是创建一个类,让类去对应表
    '''
      DB first:  帮你从db中把已创建好的表,连上db后,自动把表转化为代码中的一个个类
    Code first: 先有类和db,然后在数据库创建表  
    
    - DB first: 手动创建数据库以及表          -> ORM框架 -> 自动生成类
    - code first: 手动创建类、和数据库        -> ORM框架 -> 以及表  SQLAlchemy 
    '''
    
    
    #20181011 ORM框架 图在有道词典
    #SQLAlchemy 不进行连接,要用pymysql等进行连接
    '''
    SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,
                简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。
    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
    '''
    ORM框架初识

    sqlalchemy是codefirst
      DB first: 帮你从db中把已创建好的表,连上db后,自动把表转化为代码中的一个个类
      Code first: 先有类和db,然后在数据库创建表

      - DB first: 手动创建数据库以及表 -> ORM框架 -> 自动生成类
      - code first: 手动创建类、和数据库 -> ORM框架 -> 以及表 SQLAlchemy

    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
    
    Base = declarative_base()
    
    class UserType(Base):
        __tablename__ =  'usertype'
        id = Column(Integer,primary_key=True,autoincrement=True)
        title = Column(String(32),nullable=True,index=True)
    
    class Users(Base):
        __tablename__ =  'users'
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(32),nullable=True,index=True)
        email = Column(String(16),unique=True)
        user_type_id = Column(Integer,ForeignKey("usertype.id"))
    
        # __table_args__ = (
        #     UniqueConstraint('id','name',name='uix_id_name'),
        #     Index('ix_n_ex','name','email')
        # )
    
    def create_db():
        engine = create_engine("mysql+pymysql://root:gkx321@127.0.0.1:3306/ORMdb?charset=utf8", max_overflow=5)
        Base.metadata.create_all(engine)
        # Base.metadata.drop_all(engine)  #删除类对应的所有表
    
    def drop_db():
        engine = create_engine("mysql+pymysql://root:gkx321@127.0.0.1:3306/ORMdb?charset=utf8", max_overflow=5)
        Base.metadata.drop_all(engine)  #删除类对应的所有表
    
    engine = create_engine("mysql+pymysql://root:gkx321@127.0.0.1:3306/ORMdb?charset=utf8", max_overflow=5)
    Session = sessionmaker(bind=engine)
    session = Session() #类似pymysql中conn和cursor的综合
    
    #****增加****************
    # obj1 = UserType(title='普通用户')
    # session.add(obj1)
    # objs = [
    #     UserType(title='白银用户'),
    #     UserType(title='黄金用户')
    # ]
    # session.add_all(objs)
    
    #****查询****************
    '''
    usertype_lst = session.query(UserType).all()
    print(session.query(UserType)) #----->> SELECT usertype.id AS usertype_id, usertype.title AS usertype_title FROM usertype
    print(usertype_lst) #一个列表,包含了usertype类中的每一个对象,而这每一个对象就对应usertype表的一行数据
    for i in usertype_lst:
        print(i.id,i.title)#直接打印i会是一个对象的内存地址,应该这么打印才有值
    # ···usertype_lst = session.query(UserType.id).all() #如果query里面不是一个类,而是一个属性,那么 usertype_lst是有值的,可以直接打印
    '''
    # usertype_lst = session.query(UserType.id,UserType.title).filter(UserType.id > 2) #或者 UserType.id ==2
    # for i in usertype_lst:
    #     print(i.title)
    
    #****删除****************
    # session.query(UserType.id,UserType.title).filter(UserType.id > 2).delete()
    
    #****修改****************
    # 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({'title':UserType.title + 1},synchronize_session="evaluate")
    
    
    
    
    
    
    
    
    
    session.commit()
    session.close()
    用sqlalchemy创建类,及增删该查

    query: 类似select
    filter:类似 where
    【.】 : 类似sql里的 空格 用来分割命令的
    all : fetchone,fetchall,如果不加all,那么打印ret就只是返回一句sql语句
    #如果query里是一个类,all的取值是一个个对象,如果query里是一个 类.属性 那么ret可以直接打印出来

    子查询 select id,(select name from tb2 where id = xx) from tb2
    #sqlalchemy 支持 分组,排序,连表,通配符,子查询,limit,union,where
    #如果语句很复杂,还支持 原生sql

    #子查询 select id,(select name from tb2 where id = xx) from tb2
    #sqlalchemy 支持 分组,排序,连表,通配符,子查询,limit,union,where
    #如果语句很复杂,还支持 原生sql
    
    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
    
    Base = declarative_base()
    
    engine = create_engine("mysql+pymysql://root:gkx321@127.0.0.1:3306/ORMdb?charset=utf8", max_overflow=5)
    Session = sessionmaker(bind=engine)
    session = Session() #类似pymysql中conn和cursor的综合
    
    '''
    # 条件
    ret = session.query(Users).filter_by(name='alex').all()  #filter_by内部调用的其实是filter,只是这里用参数表示, filter Users.name='alex' 是表达式
    ret = session.query(Users).filter(Users.id > 1, Users.name == 'eric').all()  #默认是and,除非声明是or 见下方导入 or_
    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()               # 人家in_就是规定要这么写啊
    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()
    
    from sqlalchemy import and_, or_
    ret = session.query(Users).filter(and_(Users.id > 3, Users.name == 'eric')).all()  #因为默认是and,此处不声明 and_也可以的
    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]   # limit 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()  # select * from Users,Favor where Users.id = Favor.nid #相当于inner join
    
    ret = session.query(Person).join(Favor).all()   #如果两个表有设置了foreign key ,那么不用写条件,自动关联了 inner join
    ret = session.query(Person).join(Favor,isouter=True).all()   #left join, right join呢? 表换一下位置就好了。。。
    
    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()
    '''
    
    #子查询的正确写法 : .subquery()   .as_acalar()
    # 1.
    # select * from b where id in (select id from tb2)
    
    # 2 select * from (select * from tb) as B
    # q1 = session.query(UserType).filter(UserType.id > 0).subquery()
    # result = session.query(q1).all()
    # print(result)
    
    # 3
    # select
    #   id ,
    #   (select * from users where users.user_type_id=usertype.id)
    # from usertype;
    #第一次循环 拿到 id1  然后判断id1与另一张表相等,拿到一个值
    #第二次循环 拿到 id2  然后判断id2与另一张表相等,拿到一个值...
    
    # session.query(UserType,session.query(Users).filter(Users.id == 1).subquery()) #错误写法
    # session.query(UserType,Users) #上面这么写,其实还是类似笛卡儿积,达不到子查询的效果
    
    # result = session.query(UserType.id,session.query(Users).as_scalar())
    # print(result)
    
    # result = session.query(UserType.id,session.query(Users).filter(Users.user_type_id==UserType.id).as_scalar())
    # print(result)
    
    session.commit()
    session.close()
    sqlalchemy—子查询

    通过设置relationship可以减少连表带来的冗余代码,只要通过 obj.relationship_name 就可以获取表格整行数据

    # 谁有foreign key relationship就写在哪里
    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
    
    Base = declarative_base()
    
    engine = create_engine("mysql+pymysql://root:gkx321@127.0.0.1:3306/ORMdb?charset=utf8", max_overflow=5)
    Session = sessionmaker(bind=engine)
    session = Session() #类似pymysql中conn和cursor的综合
    
    '''
    获取用户信息以及与其关联的用户名称: 用SQL的时候就是要先连表
    '''
    # 问题1. 获取用户信息以及与其关联的用户类型名称(FK,Relationship=>正向操作)
    # user_list = session.query(Users,UserType).join(UserType,isouter=True)
    # print(user_list)
    # for row in user_list:
    #     print(row[0].id,row[0].name,row[0].email,row[0].user_type_id,row[1].title)
    
    # user_list = session.query(Users.name,UserType.title).join(UserType,isouter=True).all()
    # for row in user_list:
    #     print(row[0],row[1],row.name,row.title)
    
    
    
    
    '''谁有foreign key relationship就写在哪里
    relationalship~~~~
    class Users(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True, autoincrement=True)
        name = Column(VARCHAR(32), nullable=True, index=True)
        email = Column(VARCHAR(16), unique=True)
        user_type_id = Column(Integer,ForeignKey("usertype.id"))
    
        user_type = relationship("UserType",backref='xxoo') ***********创建关系! 这个backref是给usertype用的,即父表用的
    
    然后就可以使用以下方法来获取了,不用连表这么麻烦了'''
    # user_list = session.query(Users)
    # for row in user_list:
    #     print(row.name,row.id,row.user_type.title)
    
    
    # 问题2. 获取用户类型
    # type_list = session.query(UserType) 传统方式
    # for row in type_list:
    #     print(row.id,row.title,session.query(Users).filter(Users.user_type_id == row.id).all())
    
    # type_list = session.query(UserType)
    # for row in type_list:
    #     print(row.id,row.title,row.xxoo)
    
    # 设置了backref后
    # row.xxoo 就相当于 session.query(Users).filter(Users.user_type_id == row.id).all()
    
    """tb1
    1   白金
    2   黑金
    obj.xx ==> [obj,obj...]   #这叫做反向操作,设置了 backref='xx'后
    """
    
    """tb2
    1   方少伟   1
    2   成套     1
    3   小白     2
    # 正向
    ut = relationship(backref='xx')
    obj.ut ==> 相当于拿到 tb1 在id对应位置一整行数据  这叫做正向操作
    """
    
    session.commit()
    session.close()
    ORM: relationship
  • 相关阅读:
    fedora29 安装mongodb 4.0,6问题记录
    乱花渐入迷人眼------从解决jqueryEasyUI上传插件提交ajax请求谈网页调试
    thinkphp5权限仿制
    基于tornado python pandas和bootstrap上传组件的mongodb数据添加工具
    tornado下pandas ndarray乱试
    一个tornado框架下的文件上传案例
    一例tornado框架下利用python panda对数据进行crud操作
    PHP 基础语法实例及注意事项
    转:github使用教程(重装系统后遇到问题该文章帮我解决了)
    ubuntu同步系统时间命令
  • 原文地址:https://www.cnblogs.com/gkx0731/p/9820934.html
Copyright © 2020-2023  润新知