【SQLAlchemy】第4节:模型类1对多
1 思路与实现
- 定义两个表,用户表user,论坛帖子forum
- 1对多关系为user可以发送多个forum,而每个forum必须有且只有一个发送者user,所以forum当中要有一个外键指向user的id
- talk is cheap,show me the code!!!!!!
from sqlalchemy import create_engine
from sqlalchemy import Column, String, Integer, ForeignKey
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()
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)
sender_id = Column(Integer, ForeignKey('user.id')) # 定义外键
sender = relationship( # 定义模型类的关系
'User', # 引用的模型类
foreign_keys=[sender_id, ], # 本类中的外键
backref=backref('send_forums', lazy='dynamic'), # 反方向引用关系与懒加载(1的一方懒加载多的一方)
# lazy='dynamic' # 这里不需要定义,默认就是多的一方懒加载1的一方
)
2 涉及的关键字
2.1 需要导的
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship,backref
2.2 关键字解释
2.2.1 ForeignKey
物理外键:sender_id = Column(Integer,ForeignKey(‘user.id’))
- 先定义外键的类型是Integer
- 然后定义外键的指向关系(是数据库层面的引用的关系),user.id表示指向user表中的id
2.2.2 relationship
relationship是模型层的维护关系,与数据库层无关(也就是说如果改动了relationship,不需要重写更新数据库)
- ‘User’表示引用的是User类,定义了sender为本类Forum与User类的关系桥梁
- foreign_keys = [sender_id,] 定义本类中使用的外键,而sender_id在上一行中已经定义了指向user表中的id
- backref = backref(‘sender_forums’,lazy=‘dynamic’) 定义反向的维护关键字与懒加载(图上的黄字是维护关系的举例)
- lazy = ‘dynamic’ 定义的是在sender这个层面上,Forum类懒加载User类,但是不需要定义,因为默认就是懒加载,如果再定义的话会报错
3 举例:增加和查询操作
后续Session和模型类增伤改查的时候会详细讲解
from sqlalchemy import create_engine
from sqlalchemy import Column, String, Integer, ForeignKey
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()
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)
sender_id = Column(Integer, ForeignKey('user.id')) # 定义外键
sender = relationship( # 定义模型类的关系
'User', # 引用的模型类
foreign_keys=[sender_id, ], # 本类中的外键
backref=backref('send_forums', lazy='dynamic'), # 反方向引用关系与懒加载(1的一方懒加载多的一方)
# lazy='dynamic' # 这里不需要定义,默认就是多的一方懒加载1的一方
)
# -----------------------------------------------------------------------------------
from sqlalchemy.orm import sessionmaker
Base.metadata.create_all(engine) # 创建表
Session = sessionmaker() # 创建Session类
session = Session(bind=engine) # 实例化Session
user = User()
user.name = 'name1'
forum1 = Forum(
name='forum_name1',
sender=user # 定义forum1的发送者是user
)
forum2 = Forum()
forum2.name = 'forum_name2'
user.send_forums.append(forum2) # 通过user,定义user发送了forum2
session.add(user) # 因为user和forum1和forum2都有关系,仅仅保存user,就可以一起维护了相关联的forum1和forum2
session.commit() # 提交数据
user1 = session.query(User).filter_by(name='name1').first()
for forum in user1.send_forums: # 打印name='name1'用户发送的forum的name
print(forum.name)
forum = session.query(Forum).filter_by(name='forum_name1').first()
print(forum.sender.name) # 打印name='forum_name1'的forum它的发送者user
session.close()