flask之sqlalchemy ORM 一对多、多对多
一、一对多关系
爱好和人的关系,一个爱好可以对应多个人
1、models 建立表关系
# 1 导入一些模块
import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, \
relationship # 新的变成它,老的会有 from sqlalchemy.ext.declarative import declarative_base Warning
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index
# 2 得到所有表模型需要继承 基类
Base = declarative_base()
class Hobby(Base):
__tablename__ = 'hobby'
id = Column(Integer, primary_key=True)
caption = Column(String(50), default='篮球')
def __str__(self):
return self.caption
class Person(Base):
__tablename__ = 'person'
id = 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='pers') # 等同于django中的relate_name,反向查询替换表名小写的
def __str__(self):
return self.name
def __repr__(self):
return self.name
补充:
1.1 __str__ 和 __repr__ 方法
__str__ 作用:
-
__str__方法用于定义对象的“用户友好”字符串表示形式。 -
当你使用
print(obj)或str(obj)时,Python 会调用__str__方法来获取对象的字符串表示。 -
这个方法通常用于向用户展示对象的描述性信息。
user = Users(name="Alice") print(user) # 输出: Alice
__repr__作用:
-
__repr__方法用于定义对象的“开发者友好”字符串表示形式。 -
当你直接在交互式环境中输入对象名称(如
obj)或使用repr(obj)时,Python 会调用__repr__方法。 -
这个方法通常用于调试和开发,返回的字符串应该尽可能明确地描述对象的状态。
-
如果
__str__方法未定义,__repr__会作为__str__的备用方法。
def __repr__(self):
return f"<User(id={self.id}, name={self.name}, email={self.email})>"
1.2、 relationship 不会新增成字段只是用于连表查询
hobby = relationship('Hobby', backref='pers')
-
'Hobby':-
指定关联的模型类为
Hobby。
-
-
backref='pers':-
在
Hobby模型中创建一个pers属性,用于反向查询与该Hobby关联的所有Person对象。 -
例如,可以通过
hobby.pers获取所有喜欢该Hobby的Person对象。
-
正向查询
通过 Person 对象访问关联的 Hobby 对象:
person = session.query(Person).all() print(person[1].name) print(person[1].hobby) ## 结果 dapeng 乒乓球
反向查询
通过 Hobby 对象访问关联的 Person 对象:
hobby = session.query(Hobby).all() print(hobby[1]) print(hobby[1].pers) # 获取所有喜欢该 Hobby 的 Person 对象 ## 结果 乒乓球 [jingzhiz, dapeng, lisi]
2、 一对多关系新增和查询
笨办法:先添加爱好再添加人和对应爱好字段
hobby = Hobby(caption='乒乓球') session.add(hobby) person = Person(name='lisi', hobby_id=2) # hobby_id=1 只能放数字 session.add(person) session.commit() session.close()
高级点的用法
hobby 放对象,用对象做关联,但是必须用 relationship
hobby = Hobby(caption='橄榄球') person = Person(name='彭于晏', hobby=hobby) session.add(person) session.commit() session.close()
二、多对多关系
1、models创建表关系
# 1 导入一些模块
import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, \
relationship # 新的变成它,老的会有 from sqlalchemy.ext.declarative import declarative_base Warning
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index
# 2 得到所有表模型需要继承 基类
Base = declarative_base()
# 多对多
class Boy2Girl(Base):
__tablename__ = 'boy2girl'
id = Column(Integer, primary_key=True, autoincrement=True)
girl_id = Column(Integer, ForeignKey('girl.id'))
boy_id = Column(Integer, ForeignKey('boy.id'))
ctime = Column(DateTime, default=datetime.datetime.now) # 约会时间
class Girl(Base):
__tablename__ = 'girl'
id = Column(Integer, primary_key=True)
name = Column(String(64), unique=True, nullable=False)
# boy = relationship('Boy', secondary='boy2girl', backref='girls')
def __repr__(self):
return self.name
class Boy(Base):
__tablename__ = 'boy'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(64), unique=True, nullable=False)
# 与生成表结构无关,仅用于查询方便,放在哪个单表中都可以,这个字段放boy或girl表都可以
girls = relationship('Girl', secondary='boy2girl', backref='boys')
def __repr__(self):
return self.name
# # 4 创建 engine,需要手动创建数据库
engine = create_engine(
"mysql+pymysql://root:bigdata@192.168.1.238:3306/sqlalchemy01?charset=utf8",
max_overflow=0, # 超过连接池大小外最多创建的连接
pool_size=5, # 连接池大小
pool_timeout=30, # 池中没有线程最多等待的时间,否则报错
pool_recycle=-1 # 多久之后对线程池中的线程进行一次连接的回收(重置)
)
# 5 通过 engine 把上面的表模型,创建到数据库中
Base.metadata.create_all(engine)
2、多对多新增和查询
2.1 新增
新增简单用法
# 先新增人 boy = Boy(name='张三') girl = Girl(name='小红') session.add_all([boy, girl]) # 再新增约会 b = Boy2Girl(girl_id=1, boy_id=1) session.add(b) session.commit()
高级用法
一起新增多个约会
boy = Boy(name='张五') girl = Girl(name='大红红红') # 查出小红 xh = session.query(Girl).filter_by(name='小红').first() boy.girls = [girl, xh] session.add(boy) session.commit()
2.2 查询
正向查询
# 查询:张五跟谁约过 zw = session.query(Boy).filter_by(name='张五').first() print(zw.girls) # 基于对象的跨表的正向查询
反向查询
xh = session.query(Girl).filter_by(name='小红').first() print(xh.boys) # 基于对象的跨表的正向查询
注意:
这里的xh.boys 是Boy表中 girls = relationship('Girl', secondary='boy2girl', backref='boys') backref 指定的字段

浙公网安备 33010602011771号