共计 5333 个字符,预计需要花费 14 分钟才能阅读完成。
一、模型继承
1、父类没有抽象化
子类不会生成表,父类会生成表,并且将子类独有的字段放入父类表中
class Parent(db.Model):
__tablename__ = 'parent'
id = db.Column(db.Integer, primary_key=True)
uusername = db.Column(db.String(12), default='lucky')
class Son(Parent):
usex = db.Column(db.Boolean, default=True)
uage = db.Column(db.Integer, default=18)
2、父类抽象化
-
Person 父类
from exts import db class Person(db.Model): # 父类抽象化 __abstract__ = True id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(20)) age = db.Column(db.Integer)
-
子类 Man
from exts import db from .animal import Person class Man(Person): __tablename__ = "man" weight = db.Column(db.Float)
-
子类 Women
from exts import db from .animal import Person class Women(Person): __tablename__ = "women" height = db.Column(db.Float)
二、模型对应关系
1、一对多关系
-
新建 one_to-many.py 代码如下
User 模型类
class User(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) addresses = db.relationship('Address', backref='user',lazy='dynamic') def __str__(self): return self.name
Address 模型类
class Address(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) detailed_address = db.Column(db.String(50), default='详细地址') user_id = db.Column(db.Integer, db.ForeignKey('user.id')) def __str__(self): return self.detailed_address
-
代码说明
addresses = db.relationship('Address', backref='user',lazy='dynamic')
-
relationship 函数
sqlalchemy 对关系之间提供的一种便利的调用方式,关联不同的表
-
backref 参数
对关系提供反向引用的声明,在 Address 类上声明新属性的简单方法,之后可以在 my_address.user 来获取这个地址的 user
-
lazy 参数
决定了 SQLAlchemy 什么时候从数据库中加载数据,有四个可选方式
- select(默认值):SQLAlchemy 会在使用一个标准 select 语句时一次性加载数据
- joined:让 SQLAlchemy 当父级使用 JOIN 语句是,在相同的查询中加载关系
- subquery:类似 joined,但是 SQLAlchemy 会使用子查询
- dynamic:SQLAlchemy 会返回一个查询对象,在加载这些条目时才进行加载数据,大批量数据查询处理时推荐使用。
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
-
ForeignKey 参数
代表一种关联字段,将两张表进行关联的方式,表示一个 User 的外键,设定上必须要能在父表中找到对应的 id 值
-
-
一对多模型数据添加
@rel.route('/add_user/') def add_user(): u = User(name='张三') u.save() return 'add_user' @rel.route('/add_address/') def add_address(): # 俩种添加方式都可以 # a = Address(detailed_address='北京市昌平区', user_id=1) # a = Address(detailed_address='黑龙江省佳木斯市', user=User.query.get(1)) address = Address(detailed_address='辽宁省沈阳市', user=User.query.get(2)) address.save() address.save() return 'add_address'
-
一对多模型数据查询
# 查看用户有哪些地址 @rel.route('/select_address/') def select_address(): u = User.query.filter_by(name='lucky').first() print(u.addresses.all()) return 'select_address' # 查询地址所对应的用户 @rel.route('/select_user/') def select_user(): address = Address.query.first() print(address) return 'select_user'
-
一对多数据删除
# 删除用户数据 @rel.route('/delete_user/') def delete_user(): u = User.query.first() u.delete() return 'delete_user' # 删除地址数据 @rel.route('/delete_address/') def delete_address(): address = Address.query.get(3) address.delete() return 'delete_address'
2、一对一关系
-
新建 one_to_one.py 代码如下
class Wife(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(10)) husband = db.relationship("Husband", backref="wife", uselist=False) def __str__(self): return self.name class Husband(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(10)) wife_id = db.Column(db.Integer, db.ForeignKey('wife.id'), unique=True) def __str__(self): return self.name
在一对多关系基础上的父表中使用 backref 函数,并添加 uselist 参数来表示一对一关系
-
添加数据以及模型对应关系数据
# 添加妻子数据 @oto.route('/add_wife/') def add_wife(): wife = Wife(name='林心如') wife.save() return 'add_wife' # 添加丈夫数据 @oto.route('/add_husband/') def add_husband(): husband = Husband(name='霍建华', wife=Wife.query.first()) husband.save() return 'add_husband'
-
查询一对一数据
# 查询妻子的丈夫数据 @oto.route('/select_husband/') def select_husband(): w = Wife.query.first() print(w.husband) return 'select_husband' # 查询丈夫的妻子数据 @oto.route('/select_wife/') def select_wife(): h = Husband.query.first() print(h.wife) return 'select_wife'
3、多对多关系
-
新建 many_to_many.py 代码如下
tags = db.Table('tags', db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')), db.Column('page_id', db.Integer, db.ForeignKey('page.id')) ) class Page(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) con = db.Column(db.String(200), default='页面内容') tags = db.relationship('Tag', secondary=tags, backref=db.backref('pages', lazy='dynamic'), lazy='dynamic') def __str__(self): return self.con class Tag(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(20), default='标签名') def __str__(self): return self.name
如果想要用多对多关系,需要在两个类之间增加一个关联的辅助表
-
代码说明
tags = db.relationship('Tag', secondary=tags, backref=db.backref('pages', lazy='dynamic'))
- secondary 参数:指定多对多关系中关系表的名字
- backref 函数:由于在这里我们需要在每一页显示多个标签,所以使用 backref 参数添加一个反向引用,配置 Page.tags 加载后作为标签的列表
-
多对多模型数据添加
# 添加页面内容 @mtm.route('/add_pag/') def add_pag(): # page = Page(con='唐僧师徒四人为取真经,行至白虎岭前。在白虎岭内,住着一个尸魔白骨精...') page = Page(con='唐僧因悟空又打死拦路强盗,再次把他撵走。六耳猕猴精趁机变作悟空模样,抢走行李关文,又把小妖变作唐僧、八戒、沙僧模样...') page.save() return 'add_pag' # 添加标签 @mtm.route('/add_tag/') def add_tag(): # tag = Tag(name='孙悟空') # tag = Tag(name='猪八戒') # tag = Tag(name='真假美猴王') tag = Tag(name='西游记') tag.save() return 'add_tag'
-
多对多模型关系数据添加
# 添加模型对应关系数据 @mtm.route('/add_relationship/') def add_relationship(): # 查询第一页内容 page = Page.query.first() # 给第一页添加第一个标签 # page.tags.append(Tag.query.get(1)) # 给第一页添加第四个标签 page.tags.append(Tag.query.get(4)) page.save() return 'add_relationship'
-
多对多模型数据查询
# 查询页面添加了哪些标签 @mtm.route('/select_pag/') def select_pag(): # 查询第一页内容的标签 page = Page.query.first() print(page.tags.all()) return 'select_pag' # 查询标签都被哪些页面添加了 @mtm.route('/select_tag/') def select_tag(): # 查询标签 1 都被哪个 page 添加了 tag = Tag.query.first() print(tag.pages.all()) return 'select_tag'
-
多对多模型数据删除
# 删除模型对应关系数据 @mtm.route('/delete_relationship_data/') def delete_relationship_data(): # 第一页内容移除第一个标签 page = Page.query.first() page.tags.remove(Tag.query.get(1)) page.save() return 'delete_relationship_data'
正文完
星哥玩云-微信公众号