首先,在使用 flask_sqlalchemy 中继承自 db.Model 类的子类,我们不能因为这个类用来与数据库交互,且语法与sql很相似
而把它固象思维的想成就是一张表。他不是表,他只是表的映射,他可以比表更加强大。类和表的映射,使我们可以使用面向对象的方式
去思考表。
类,他有字段,属性,方法。我们仅仅使用字段来做与表结构的映射。我们可以使用属性(关系)来定义一张表到另一张表的面向对象视角
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.String(255),primary_key=True)
name = db.Column(db.String(64), unique=True, index=True)
skill = db.relationship('Skill',backref=db.backref('user'))
def __init__(self, **kwargs):
for key in kwargs:
setattr(self, key, kwargs[key])
self.id = str(uuid.uuid1())
def __repr__(self):
return '<User %r>' % self.name
class Skill(db.Model):
__tablename__ = 'skill'
id = db.Column(db.String(255),primary_key=True)
name = db.Column(db.String(64), unique=True)
user_id = db.Column(db.String(255), db.ForeignKey('user.id'), nullable=False)
def __init__(self, **kwargs):
for key in kwargs:
setattr(self, key, kwargs[key])
self.id = str(uuid.uuid1())
def __repr__(self):
return '<Skill %r>' % self.name
db.create_all()
user1 = User(name = 'li')
db.session.add_all([user1])
db.session.commit()
skill1 = Skill(name = 'java',user_id = user1.id)
skill2 = Skill(name = 'python',user_id = user1.id)
db.session.add_all([user1,skill1,skill2])
db.session.commit()
uli = User.query.filter_by(name = 'li').one()
print(uli.skill)
skillp = Skill.query.filter_by(name = 'python').one()
print(skillp.user)
>>>输出
#[<Skill 'java'>, <Skill 'python'>]
#<User 'li'>
1.db.Relationship()第一个参数表明这个关系的另一端是哪个模型(类)。
如果模型类尚未定义,可使用字符串形式指定。
2.User.skill 将访问 Skill 表中符合 User 的所有技能模型
2.db.Relationship()第二个参数backref,将向Skill类中添加一个user属性,从而定义反向关系。
这一属性可替代 user_id 访问 User 模型, Skill.user 此时获取的是模型对象,而不是外键的值。
上面例子是一个一对多关系的应用,下面来看一看多对多关系的例子
from database import db
import uuid
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.String(255),primary_key=True)
name = db.Column(db.String(64), unique=True, index=True)
roles = db.relationship('UsersRoles', backref=db.backref('user'))
def __init__(self, **kwargs):
for key in kwargs:
setattr(self, key, kwargs[key])
self.id = str(uuid.uuid1())
def __repr__(self):
return '<User %r>' % self.name
class Role(db.Model):
__tablename__ = 'role'
id = db.Column(db.String(255),primary_key=True)
name = db.Column(db.String(64), unique=True)
users = db.relationship('UsersRoles', backref=db.backref('role'))
def __init__(self, **kwargs):
for key in kwargs:
setattr(self, key, kwargs[key])
self.id = str(uuid.uuid1())
def __repr__(self):
return '<Role %r>' % self.name
class UsersRoles(db.Model):
__tablename__ = "users_roles"
user_id = db.Column(db.String(255), db.ForeignKey('user.id'), nullable=False)
role_id = db.Column(db.String(255), db.ForeignKey('role.id'), nullable=False)
id = db.Column(db.String(255), primary_key=True, unique=True)
def __init__(self, **kwargs):
self.id = str(uuid.uuid1())
for key in kwargs:
setattr(self, key, kwargs[key])
建表
# db.create_all()
#
# user1 = User(name = "fang")
# user2 = User(name = "sun")
#
# role1 = Role(name = "talk")
# role2 = Role(name = "smoke")
#
# db.session.add_all([role1,role2,user1,user2])
# db.session.commit()
#
#
# ur1 = UsersRoles(user_id = user1.id,role_id = role1.id)
# ur2 = UsersRoles(user_id = user1.id,role_id = role2.id)
# ur3 = UsersRoles(user_id = user2.id,role_id = role2.id)
# db.session.add_all([ur1,ur2,ur3])
# db.session.commit()
ufang = User.query.filter_by(name = 'fang').one() # 姓名为 fang 的用户对象
urids = ufang.roles # 在中间表 UsersRoles 中 user_id 为对象fang 的对象列表
print(urids[0].role) #列表第一个对象对应的在Role表中的规则
print(urids[1].role) #列表第二...
>>>输出
# <Role 'talk'>
# <Role 'smoke'>
rsmoke = Role.query.filter_by(name = 'smoke').one()
urids2 = rsmoke.users
print(urids2[0].user)
print(urids2[1].user)
>>>输出
# <User 'fang'>
# <User 'sun'>
可以看出
1.基本表的关系属性可以返回中间表中符合基本表条件的模型对象
2.中间表的反向关系属性可以返回对应的符合条件的基本表的模型对象
3.注意所有操作的返回都是类的实例。
4.以上所有的返回都是对象,并不是字段,之所以输出格式为 <User 'sun'> 形式,是因为
def __repr__(self):
return '<Role %r>' % self.name
中定义了格式。
flask_sqlalchemy中一对多,多对多关系的理解与实践
最新推荐文章于 2022-09-01 09:51:05 发布