flask_sqlalchemy中一对多,多对多关系的理解与实践

首先,在使用 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
    中定义了格式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值