• 一对多表操作


    一对多表操作

    一、创建建表

    # model.py
    import datetime
    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index
    from sqlalchemy.orm import relationship
    
    Base = declarative_base()
    
    # make_declarative_base
    class Hobby(Base):
        __tablename__ = 'hobby'
        id = Column(Integer, primary_key=True)
        caption = Column(String(50), default='篮球')
    
    class Person(Base):
        __tablename__ = 'person'
        nid = Column(Integer, primary_key=True)
        name = Column(String(32), index=True, nullable=True)
        # hobby指的是tablename而不是类名,uselist=False
        hobby_id = Column(Integer, ForeignKey("hobby.id"))
    
        # 跟数据库无关,不会新增字段,只用于快速链表操作
        # 类名,backref用于反向查询
        hobby = relationship('Hobby', backref='perss')
    
        def __repr__(self):
            return self.name
    
    
    def init_db():
        """
        根据类创建数据库表
        :return:
        """
        engine = create_engine(
            "mysql+pymysql://root:root@127.0.0.1:3306/db_flask?charset=utf8",
            max_overflow=0,  # 超过连接池大小外最多创建的连接
            pool_size=5,  # 连接池大小
            pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
            pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
        )
    
        Base.metadata.create_all(engine)
    
    
    def drop_db():
        """
        根据类删除数据库表
        :return:
        """
        engine = create_engine(
            "mysql+pymysql://root:root@127.0.0.1:3306/db_flask?charset=utf8",
            max_overflow=0,  # 超过连接池大小外最多创建的连接
            pool_size=5,  # 连接池大小
            pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
            pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
        )
    
        Base.metadata.drop_all(engine)
    
    
    if __name__ == '__main__':
        # 创建表
        init_db()
    
        # 删除表
        # drop_db()
    

    二、添加数据

    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    from model import Users, Hobby, Person
    
    engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/db_flask", max_overflow=0, pool_size=5)
    Session = sessionmaker(bind=engine)
    session = Session()
    
    # 1. 添加数据
    
    # 方式一
    session.add_all([
        Hobby(caption='乒乓球'),
        Hobby(caption='羽毛球'),
        Person(name='张三', hobby_id=1),
        Person(name='李四', hobby_id=2),
    ])
    
    # 方式二
    # Hobby 爱好会自动插入一个爱好,即使存在也会插入数据
    # 正向查询字段hoppy添加
    person = Person(name='张三', hobby=Hobby(caption='跑腿'))
    session.add(person)
    
    # 方式三
    
    hb = Hobby(caption='羽毛球')  
    # 通过反向查询字段,添加数据perss 是关联字段
    hb.perss = [Person(name='文飞'), Person(name='波波')]
    
    session.add(hb)
    session.commit()
    

    三、正、反向查询

    3.1 正向查询

    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    from model import Users, Hobby, Person
    
    engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/db_flask", max_overflow=0, pool_size=5)
    Session = sessionmaker(bind=engine)
    session = Session()
    
    # 2. relationship正向查询
    person = session.query(Person).first()
    print(person.name)
    
    # 正向查询, 当前类中有外键成为正向查询,正向查询只会有一个与其对应的爱好(单条记录)
    print(person.hobby)
    print(person.hobby.caption)
    

    3.1 反向查询

    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    from model import Users, Hobby, Person
    
    engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/db_flask", max_overflow=0, pool_size=5)
    Session = sessionmaker(bind=engine)
    session = Session()
    
    # 3. relationship 反向查询
    hobby = session.query(Hobby).filter(Hobby.id == 1).first()
    print(hobby.caption)
    # 对象列表,反向查询的结果是一个类表对象(因为是一对多的关系,在person可能有多个爱好被被关联),所以要使用循坏一个个遍历
    print(hobby.perss)
    print(hobby.perss[0].nid, hobby.perss[0].name)
    

    3.3 断关联连表查询

    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    from model import Users, Hobby, Person
    
    engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/db_flask", max_overflow=0, pool_size=5)
    Session = sessionmaker(bind=engine)
    session = Session()
    
    # 3. 断关联
    # 断关联:是两张表中没有设置外键关联,所以只能通过逻辑进行关联,使用.join( Person.hobby_id == Hobby.id)
    # Person.hobby_id == Hobby.id 断关联这个条件必须要写,通过join实现表之间的关联
    # isouter=True 左关联,False为 inner join 等值关联
    # query中的表和join表来调换表的查询关系
    ret = session.query(Person).join(Hobby, Person.hobby_id == Hobby.id, isouter=False)
    print(ret)
    
    # 设置了外键关联,就不需要设置 Person.hobby_id == Hobby.id 条件
    person_list = session.query(Hobby).join(Person, isouter=True)
    print(person_list)
    
    person_list = session.query(Person, Hobby).join(Hobby).all()
    print(person_list)
    for row in person_list:
        # print(row.name,row.caption)
        # 第一个为person对象, 第二位hobby对象
        print(row[0].name, row[1].caption)
    

    3.4 通过relationship连表查询

    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import create_engine
    from model import Users, Hobby, Person
    
    engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/db_flask", max_overflow=0, pool_size=5)
    Session = sessionmaker(bind=engine)
    session = Session()
    # 通过relationship
    person_list = session.query(Person).all()
    
    print(person_list)
    
    for row in person_list:
        print(row.name, row.hobby.caption)
        
    # obj = session.query(Hobby).filter(Hobby.id == 1).first()
    # persons = obj.perss
    # print(persons)
        
    

    三、总结

    • 添加数据:可以通过add_all添加数据并设置关联外键字段值,还可以通过正反向查询向添加表之间的关系,会自定设置关联的外键值
    • 正向查询:当前表中有外键字段称为正向查询,正向查询单条数据对一个爱好数据
    • 反向查询:当前表中没有外键字段称为反向查询,反向查询单条数据可会被多个人喜欢,所以查出来为列表对象,是一个集合
    • 连表查询:可以通过两种方式进行查询,一种是通过表之间的关键关系通过 .join方法实现连表查询,需要注意的是表之间是否有级联关系,也就是是否设置了外键,如果没有则需要在.join中通过逻辑条件实现连表查询,通过调至query和.join中类名实现左右连接查询,第二种方式就是通过正反向查询实现连表查询
    在当下的阶段,必将由程序员来主导,甚至比以往更甚。
  • 相关阅读:
    linux-磁盘挂载脚本
    VSCode插件
    数据模拟--Mock.js
    Vue学习笔记之组件
    Vue学习笔记之动画
    Echarts柱状图常用配置项
    Vue学习笔记之总体结构
    JSON数据格式开发规范
    苹果电脑和手机浏览器的区分
    二维码生成插件(jquery.qrcode.js)说明文档
  • 原文地址:https://www.cnblogs.com/randysun/p/15518319.html
Copyright © 2020-2023  润新知