Flask ORM 学习笔记Part03:数据操作,以及关系关联演示
  qdp7fV9qUjiK 2023年12月06日 15 0

在前两部分的学习笔记中,讲了model类的建立与表的创建以及通过flask-migrate对数据库进行迁移。本篇继续,开始实际演示对数据进行操作。

以下示例基于Part01中的model类

一对一关系

在model中 Account 与 Profile之间是一对一关系

class Account(Base):
    __tablename__ = "accounts"
    account_name = db.Column(db.String(50), unique=True, nullable=False)
    account_email = db.Column(db.String(120), unique=True, nullable=False)
    # 与Profile建立一对一关系
    profile = db.relationship('Profile', backref='account', uselist=False)

    def __init__(self, account_name, account_email):
        self.account_name = account_name
        self.account_email = account_email

    def __repr__(self):
        return '<Account %r %r>' % self.account_name, self.account_email


class Profile(Base):
    __tablename__ = "profiles"
    fullname = db.Column(db.String(100))
    gender = db.Column(db.String(10))
    # 外键
    account_id = db.Column(db.Integer, db.ForeignKey('accounts.id'), unique=True)

    def __init__(self, fullname, gender):
        self.fullname = fullname
        self.gender = gender

    def __repr__(self):
        return '<Profile %r %r>' % self.fullname, self.gender

可以通过创建对象,然后通过对应的类属性来创建关联。

data_1v1.py

# 导入需要使用的模型和数据库实例
from model import Account, Profile, Project, Host, db
from app import app

# 在 Flask 应用上下文中执行以下代码
with app.app_context():
    # 分别创建三个 Account 对象和三个 Profile 对象
    a1 = Account(account_name='lisi', account_email='a1@123.com')
    a2 = Account('xiaoni', 'a2@123.com')

    pf1 = Profile(fullname='里斯', gender='M')
    pf2 = Profile('小妮', 'F')

    # 由于在 model 中定义了这两个类的 relationship,并使用了 backref,
    # 所以这两个类的对象有相应的属性进行关联,
    # Account 类对象可以使用 profile 属性来获取 Profile 对象,
    # 同理,Profile 类对象可以使用 account 属性来获取 Account 对象。
    a1.profile = pf1
    pf2.account = a2

    # 将对象添加到数据库会话中
    db.session.add(a1)
    db.session.add(a2)
    db.session.add(pf1)
    db.session.add(pf2)

    # 提交更改到数据库
    db.session.commit()

    # 通过查询获取 Account 对象
    q_a1 = Account.query.filter_by(account_name='lisi').first()

    # 打印查询结果
    print('q_a1')
    print(q_a1.account_name, q_a1.account_email, q_a1.profile.fullname, q_a1.profile.gender)

直接执行上述代码可以得到结果

Flask ORM 学习笔记Part03:数据操作,以及关系关联演示_多对多

上述代码定义a1、a2 两个Account对象,pf1、pf2两个Profile对象,通过为各自属性赋值来实现relationship的关联,然后提交更改到数据库

一对多关系

在model中 Project与Host之间是一对多关系

注意:可以通过替换lazy的值来看查看不同返回,具体参考本系列文档的Part01

# 一对多关系
class Project(Base):
    __tablename__ = "projects"
    project_name = db.Column(db.String(50), unique=True, nullable=False)
    project_webhook = db.Column(db.String(150))
    # 与Host建立一对多关系
    hosts = db.relationship('Host', backref='project', lazy=True)
    # 与Accounts通过中间表建立多对多关系
    accounts = db.relationship('Account', secondary='account_project', backref=db.backref('projects', lazy=True))

    def __init__(self, project_name, project_webhook):
        self.project_name = project_name
        self.project_webhook = project_webhook

    def __repr__(self):
        return '<Project %r %r>' % self.project_name, self.project_webhook


class Host(Base):
    __tablename__ = "hosts"
    hostname = db.Column(db.String(50))
    ip = db.Column(db.String(15))
    project_id = db.Column(db.Integer, db.ForeignKey('projects.id'))

    def __init__(self, hostname, ip):
        self.hostname = hostname
        self.ip = ip

    def __repr__(self):
        return '<Host %r %r>' % self.hostname, self.ip

同样的示例

data_1vm.py

from model import Account, Profile, Project, Host, db
from app import app

# 在 Flask 应用上下文中执行以下代码
with app.app_context():
    # 创建两个Project对象,四个Host对象,并关联
    p1 = Project(project_name='p1', project_webhook='http://xxx.com/webhook')
    p2 = Project('p2', 'http://xxx.com/webhook')

    h1 = Host(hostname='h1', ip='127.0.0.1')
    h2 = Host('h2', '127.0.0.2')
    h3 = Host(hostname='h3', ip='127.0.0.3')
    h4 = Host('h4', '127.0.0.4')

    # 建立关联关系,p1与h1 h2建立关联,p2与h3 h4建立关联
    # 从两个方向进行关联

    p1.hosts.append(h1)
    p1.hosts.append(h2)
    
    h3.project = p2
    # h4这种通过外键方式进行管理,理论上是可以的,
    # 但是由于被关联对象p2还没有提交到数据库,所以关联的结果只会是一个寂寞。
    # h4.project_id = p2.id


    db.session.add(p1)
    db.session.add(p2)
    db.session.add(h1)
    db.session.add(h2)
    db.session.add(h3)
    db.session.add(h4)

    # 提交更改到数据库
    db.session.commit()

    q_p1 = Project.query.filter_by(project_name='p1').first()
    print('q_p1')
    print(q_p1.project_name, q_p1.project_webhook)
    p1_host = q_p1.hosts
    print('与P1关联的Host')
    for h in p1_host:
        print(h.hostname, h.ip)
    print("~~~~~~~~~~~")
    q_p2 = Project.query.filter_by(project_name='p2').first()
    print('q_p2')
    print(q_p2.project_name, q_p2.project_webhook)
    print('与P2关联的Host')
    p2_host = q_p2.hosts
    for h in p2_host:
        print(h.hostname, h.ip)

直接执行上述代码可以得到结果

Flask ORM 学习笔记Part03:数据操作,以及关系关联演示_一对多_02

多对多关系

在model中 Account与之间多对多关系。

注意:可以通过替换lazy的值来看查看不同返回,具体参考本系列文档的Part01

class Account(Base):
    __tablename__ = "accounts"
    account_name = db.Column(db.String(50), unique=True, nullable=False)
    account_email = db.Column(db.String(120), unique=True, nullable=False)
    # 与Profile建立一对一关系
    profile = db.relationship('Profile', backref='account', uselist=False)

    def __init__(self, account_name, account_email):
        self.account_name = account_name
        self.account_email = account_email

    def __repr__(self):
        return '<Account %r %r>' % self.account_name, self.account_email

    
class Project(Base):
    __tablename__ = "projects"
    project_name = db.Column(db.String(50), unique=True, nullable=False)
    project_webhook = db.Column(db.String(150))
    # 与Host建立一对多关系
    hosts = db.relationship('Host', backref='project', lazy=True)
    # 与Accounts通过中间表建立多对多关系
    accounts = db.relationship('Account', secondary='account_project', backref=db.backref('projects', lazy=True))

    def __init__(self, project_name, project_webhook):
        self.project_name = project_name
        self.project_webhook = project_webhook

    def __repr__(self):
        return '<Project %r %r>' % self.project_name, self.project_webhook
    
    
# 多对多关系
account_project = db.Table(
    'account_project',
    db.Column('account_id', db.Integer, db.ForeignKey('accounts.id')),
    db.Column('project_id', db.Integer, db.ForeignKey('projects.id'))
)

data_mvm.py

from model import Account, Profile, Project, Host, db
from app import app

# 在 Flask 应用上下文中执行以下代码
with app.app_context():
    # 上文中已经在数据库中创建了两个Account和两个Project,这里直接读取出来
    a1 = Account.query.filter_by(account_name="lisi").first()
    a2 = Account.query.filter_by(account_name="xiaoni").first()

    p1 = Project.query.filter_by(project_name="p1").first()
    p2 = Project.query.filter_by(project_name="p2").first()

    # 通过relationship进行关联
    a1.projects = [p1, p2]
    a2.projects = [p1]

    db.session.commit()

    q_a1 = Account.query.filter_by(account_name="lisi").first()
    print(q_a1.account_name, q_a1.account_email)
    print('关联的Project')
    for p in q_a1.projects:
        print(p.project_name, p.project_webhook)
        print('project {} 关联的Host'.format(p.project_name))
        for h in p.hosts:
            print(h.hostname, h.ip)
    print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
    q_p1 = Project.query.filter_by(project_name="p1").first()
    print(q_p1.project_name, q_p1.project_webhook)
    print('关联的Account')
    for a in q_p1.accounts:
        print(a.account_name, a.account_email)

Flask ORM 学习笔记Part03:数据操作,以及关系关联演示_多对多_03

未完待续:

marshmallow 的使用 序列化与反序列化

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月06日 0

暂无评论

推荐阅读
qdp7fV9qUjiK