本章节介绍
SQLAlchemy
的表关系,主要分为以下几种
在多表关联中,常见的是一对多的关系,但是有时候我们也会听到多对一的关系,其实他们仅仅是站在不同的角度上来看的表关系,(本案例中采用用户与文章来说明)
具体的代码实现
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='')
的参数介绍module
关联的数据模型(如果是在当前的上面可以不加引号)backref
在关联的module
中添加属性uselist
默认是True
表示一对多的关系,如果是一对一的关系就要设置False
cascade
自动关系处理(比如一对一中删除父表数据,子表数据是否删除)cascade
几个属性的介绍all
:所有操作都会自动处理到关联对象上save-update
:关联对象自动添加到会话上delete
:关联对象自动从会话中删除delete-orphan
:属性中去掉关联对象,则会话中会自动删除关联对象merge
:session.merge()
时会处理关联对象refresh-expire
: session.expire()
时会处理关联对象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)