sqlalchemy在python中的使用(表之间的关系)四

本章节介绍SQLAlchemy的表关系,主要分为以下几种

  • 1、一对多关系
  • 2、一对一的关系
  • 3、多对多的关系

一、一对多的关系

在多表关联中,常见的是一对多的关系,但是有时候我们也会听到多对一的关系,其实他们仅仅是站在不同的角度上来看的表关系,(本案例中采用用户与文章来说明)

  • 1、一个用户可以写多篇文章(用户对文章是一对多的关系)
  • 2、文章只能有一个用户(多对一的关系)

具体的代码实现

  • 1、基本的导包

    from sqlalchemy import Column, Integer, String, DateTime, Boolean, TIMESTAMP, func
    from sqlalchemy.orm import relationship
    
    from sqlalchemy_demo.connect import Base
    from sqlalchemy import ForeignKey
    复制代码
  • 2、创建一个用户表的module

    class UserModule(Base):
        """
        创建一个用户的数据模型
        """
        __tablename__ = 'user'
    
        id = Column(Integer, primary_key=True, autoincrement=True, comment='用户id')
        user_name = Column(String(30), nullable=False, unique=True, comment='用户名')
        password = Column(String(64), nullable=False, comment='用户密码')
    
        def __repr__(self):
            return 'User({},{})'.format(self.user_name, self.password)
    复制代码
  • 3、创建一个文章表的module

    class ArticleList(Base):
        """
        文章列表页面
        """
        __tablename__ = 'article_list'
    
        id = Column(Integer, primary_key=True, autoincrement=True, comment='文章id')
        title = Column(String(100), nullable=False, default='', comment='文章标题')
        
        def __repr__(self):
            return 'ArticleList({})'.format(self.title)
    复制代码
  • 4、在子表中(相对来说是多的那端)使用ForeignKey关联到父表(注意数据类型要一致)

    class ArticleList(Base):
        """
        文章列表页面
        """
        ...
        # 外键关联(关联的key的类型要和定义的类型一致)
        user_id = Column(Integer, ForeignKey(UserModule.id), comment='文章作者')
        ...
    复制代码
  • 5、在父表中使用relationship方法来引用子表的数据(就是说关联了,可以通过父表查询到子表的数据[本案例中:根据用户查询到文字])

    class UserModule(Base):
        """
        创建一个用户的数据模型
        """
        ...
        article_list = relationship('ArticleList')
        ...
    复制代码
  • 6、上面仅仅是建立的父表可以访问到子表的数据,如果要子表也要访问到父表的数据就在relationship中多加一个参数backref

    class UserModule(Base):
        """
        创建一个用户的数据模型
        """
        ...
        article_list = relationship('ArticleList', backref='user')
        ...
    复制代码
  • 7、子表访问父表还有另外一种方式,使用back_populates(和上面方法任选一个)

    • 在父表中

      class UserModule(Base):
      """
      创建一个用户的数据模型
      """
      ...
      
      article_list = relationship('ArticleList', back_populates='user')
      
      复制代码
    • 在子表中

      class ArticleList(Base):
      """
      文章列表页面
      """
      __tablename__ = 'article_list'
      ...
      # 外键关联
      user_id = Column(Integer, ForeignKey(UserModule.id), comment='文章作者')
      # 通过关联起来,这样在文章列表页面可以获取用户表的信息
      user = relationship(UserModule, back_populates='article_list')
      复制代码
  • 8、测试一(父表查询到子表数据)

    ...
    def query_user():
        rows = dbSession.query(UserModule).first() # 获取到父表第一条数据
        print(rows.article_list) # 获取
    ...
    复制代码
  • 9、测试二(子表查询到父表数据)

    ...
    def query_user():
        rows = dbSession.query(ArticleList).first() # 获取到文章的第一条数据
        print(rows.user) # 获取文章的作者
    ...
    复制代码

二、一对一的关系

常见的一对一的关系,一般是表的扩展,比如用户表及用户扩展表,文章及文章详情这样的,操作方式也很简单,只要在一对多的基础上加上uselist=False就可以

  • 1、用户模型

    class UserModule(Base):
        """
        创建一个用户的数据模型
        """
        __tablename__ = 'user'
    
        id = Column(Integer, primary_key=True, autoincrement=True, comment='用户id')
        user_name = Column(String(30), nullable=False, unique=True, comment='用户名')
        password = Column(String(64), nullable=False, comment='用户密码')
    	 # 一对多关系中关联文章列表的
        article_list = relationship('ArticleList', backref='user')
    
        def __repr__(self):
            return 'User({},{})'.format(self.user_name, self.password)
    复制代码
  • 2、用户扩展表

    class UserExtendModule(Base):
        """
        用户扩展的模型
        """
        __tablename__ = 'user_extend'
        id = Column(Integer, primary_key=True, autoincrement=True, comment='id')
        gender = Column(String(3), nullable=True, comment='性别')
        birthday = Column(DateTime, nullable=True, comment='出生年月')
        position = Column(String(20), nullable=True, comment='职位')
    	 # 外键关联到用户表
        user_id = Column(Integer, ForeignKey(UserModule.id), unique=True, comment='关联父id')
    	 # 创建关系,用户扩展表与用户表建立关系
        user = relationship('UserModule', backref='user_detail', uselist=False, cascade='all')
    
        def __repr__(self):
            return 'user extend({},{}, {})'.format(self.gender, self.birthday, self.position)
    复制代码
  • 3、测试代码

    • 1.用户表查找到用户扩展表

      def query_user():
          rows = dbSession.query(UserModule).first()
          print(dir(rows))
          print(rows.user_detail)
      复制代码
    • 2.反向查找(用户扩展表查找到用户)

      def query_user():
          rows = dbSession.query(UserExtendModule).first()
          print(dir(rows))
          print(rows.user)
      复制代码

三、关于relationship(module, backref='', uselist=True, cascade='')的参数介绍

  • 1、module关联的数据模型(如果是在当前的上面可以不加引号)
  • 2、backref在关联的module中添加属性
  • 3、uselist默认是True表示一对多的关系,如果是一对一的关系就要设置False
  • 4、cascade自动关系处理(比如一对一中删除父表数据,子表数据是否删除)

四、关于cascade几个属性的介绍

  • 1、all:所有操作都会自动处理到关联对象上
  • 2、save-update:关联对象自动添加到会话上
  • 3、delete:关联对象自动从会话中删除
  • 4、delete-orphan:属性中去掉关联对象,则会话中会自动删除关联对象
  • 5、merge:session.merge()时会处理关联对象
  • 6、refresh-expire: session.expire()时会处理关联对象
  • 7、expunge:session.expunge()时会处理关联对象

五、多对多的关系

mysql中处理多对多的关系的时候,我们都是创建一个第三张表,使用上面的一对多的技术,本案例使用(文章与tag来描素多对多的关系)

  • 1、文章表

    class ArticleList(Base):
        """
        文章列表页面
        """
        __tablename__ = 'article_list'
    
        id = Column(Integer, primary_key=True, autoincrement=True, comment='文章id')
        title = Column(String(100), nullable=False, default='', comment='文章标题')
        # 外键关联
        user_id = Column(Integer, ForeignKey(UserModule.id), comment='文章作者')
    
        def __repr__(self):
            return 'ArticleList({})'.format(self.title)
    复制代码
  • 2、创建一个tag

    class TagModule(Base):
        """
        文章Tag模型
        """
        __tablename__ = 'tag'
        id = Column(Integer, primary_key=True, autoincrement=True, comment='主键')
        name = Column(String(30), nullable=False, default='', comment='tag名字')
    
        def __repr__(self):
            return 'TagModule({},{})'.format(self.id, self.name)
    复制代码
  • 3、导包Table

    from sqlalchemy import ForeignKey, Table
    复制代码
  • 4、创建中间表

    article_tag = Table(
        'article_tag',
        Base.metadata,
        Column('article_id', Integer, ForeignKey(ArticleList.id), primary_key=True, comment='文章id'),
        Column('tag_id', Integer, ForeignKey(TagModule.id), primary_key=True, comment='tag表id')
    )
    复制代码
  • 5、在TagModule数据模型中新增关联关系

    class TagModule(Base):
        """
        文章Tag模型
        """
        # secondary指向中间表,是表名
        ...
        tag_article = relationship(ArticleList, backref='tags', secondary='article_tag')
        ...
    复制代码
  • 6、手动插入数据

  • 7、测试

    • 1.根据文章查找到tag

      def query_user():
          rows = dbSession.query(ArticleList).first()
          print(dir(rows))
          print(rows.tags)
      复制代码
    • 2.从tag表中查找文章

      def query_user():
          rows = dbSession.query(TagModule).first()
          print(dir(rows))
          print(rows.tag_article)
      复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值