【SQLAlchemy】第5节:模型类多对多
1 思路与实现
- 用户user和帖子forum,存在收藏关系,一个用户可以收藏多个帖子,一个帖子也可以被多个用户收藏,这是一个简单的多对多问题
- 需要3张表,用户表、帖子表和中间表
- 如果中间表仅仅保存了用户的id和帖子的id,就太简单了,现在产品经理有这样的需求,需要记录用户的哪个时间收藏了哪个帖子,所以中间表需要多一个字段,DateTime
(多对多关系是MySQL的基础,我假设大家已经具备了这个知识,如果表与表间的定义关系不清楚,可以看下我博客里面关于MySQL的部分)
代码实现:
from sqlalchemy import create_engine
from sqlalchemy import Column, String, Integer, ForeignKey, Table,DateTime
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine(
'mysql+pymysql://root:12345@localhost:3306/db_sqlalchemy_notebook',
echo=False
)
Base = declarative_base()
import datetime
# 中间表,需要写在最前面
user_forum_collection = Table(
'user_forum_collection', # 中间表的名字
Base.metadata, # 传递metadata,记住这个写法就好
Column('id', Integer, primary_key=True, autoincrement=True), # 如果再中间表中定义主键,除了primary_key=True以外,必须加上autoincrement=True,否则报错
Column('user_id', Integer, ForeignKey('user.id')), # 引用user.id
Column('forum_id', Integer, ForeignKey('forum.id')), # 引用forum.id
Column('createDatetime',DateTime,default=datetime.datetime.now(),nullable=False) # 用户收藏帖子的时间
)
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(16), nullable=False)
class Forum(Base):
__tablename__ = 'forum'
id = Column(Integer, primary_key=True)
name = Column(String(200), nullable=False)
collectors = relationship( # 模型类关系
'User', # 引用的模型类
secondary=user_forum_collection, # 中间表
backref=backref('collect_forums', lazy='dynamic'), # 反向引用关系与反向懒加载
lazy='dynamic', # 正向懒加载
)
2 中间表解释
需要新导入的包:
from sqlalchemy import Table
- 中间表一般不采用Class的方式来定义,而使用Table
- Column中第一参数是列明,而不是类型了
- Column(‘id’, Integer, primary_key=True, autoincrement=True)
- 中间表如果定义主键的话,除了primary_key=True,还必须加上autoincrement=True,否则保存
- 外键引用,其实也可以加上primary_key=True(官方爱这么写,我觉得不加也行)
- 例如:Column(‘user_id’, Integer, ForeignKey(‘user.id’),primary_key=True)
3 relationship关系维护
- secondary=中间表
- 如果有中间表的话,最好定义正向和反向都是懒加载,即lazy=‘dynamic’