【SQLAlchemy】第4节:模型类1对多

1 思路与实现

  • 定义两个表,用户表user,论坛帖子forum
  • 1对多关系为user可以发送多个forum,而每个forum必须有且只有一个发送者user,所以forum当中要有一个外键指向user的id
  • talk is cheap,show me the code!!!!!!
from sqlalchemy import create_engine
from sqlalchemy import Column, String, Integer, ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine(
    'mysql+pymysql://root:12345@localhost:3306/db_sqlalchemy_notebook',
    echo=False
)

Base = declarative_base()


class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    name = Column(String(16), nullable=False)  # 用户名


class Forum(Base):
    __tablename__ = 'forum'

    id = Column(Integer, primary_key=True)
    name = Column(String(200), nullable=False)
    sender_id = Column(Integer, ForeignKey('user.id'))  # 定义外键
    sender = relationship(  # 定义模型类的关系
        'User', # 引用的模型类
        foreign_keys=[sender_id, ], # 本类中的外键
        backref=backref('send_forums', lazy='dynamic'), # 反方向引用关系与懒加载(1的一方懒加载多的一方)
        # lazy='dynamic'  # 这里不需要定义,默认就是多的一方懒加载1的一方
    )

2 涉及的关键字

2.1 需要导的


from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship,backref

2.2 关键字解释

2.2.1 ForeignKey

物理外键:sender_id = Column(Integer,ForeignKey(‘user.id’))

  • 先定义外键的类型是Integer
  • 然后定义外键的指向关系(是数据库层面的引用的关系),user.id表示指向user表中的id
    在这里插入图片描述

2.2.2 relationship

在这里插入图片描述

relationship是模型层的维护关系,与数据库层无关(也就是说如果改动了relationship,不需要重写更新数据库)

  • ‘User’表示引用的是User类,定义了sender为本类Forum与User类的关系桥梁
  • foreign_keys = [sender_id,] 定义本类中使用的外键,而sender_id在上一行中已经定义了指向user表中的id
  • backref = backref(‘sender_forums’,lazy=‘dynamic’) 定义反向的维护关键字与懒加载(图上的黄字是维护关系的举例)
  • lazy = ‘dynamic’ 定义的是在sender这个层面上,Forum类懒加载User类,但是不需要定义,因为默认就是懒加载,如果再定义的话会报错

3 举例:增加和查询操作

后续Session和模型类增伤改查的时候会详细讲解

from sqlalchemy import create_engine
from sqlalchemy import Column, String, Integer, ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine(
    'mysql+pymysql://root:12345@localhost:3306/db_sqlalchemy_notebook',
    echo=False
)

Base = declarative_base()


class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    name = Column(String(16), nullable=False)  # 用户名


class Forum(Base):
    __tablename__ = 'forum'

    id = Column(Integer, primary_key=True)
    name = Column(String(200), nullable=False)
    sender_id = Column(Integer, ForeignKey('user.id'))  # 定义外键
    sender = relationship(  # 定义模型类的关系
        'User', # 引用的模型类
        foreign_keys=[sender_id, ], # 本类中的外键
        backref=backref('send_forums', lazy='dynamic'), # 反方向引用关系与懒加载(1的一方懒加载多的一方)
        # lazy='dynamic'  # 这里不需要定义,默认就是多的一方懒加载1的一方
    )

# -----------------------------------------------------------------------------------
from sqlalchemy.orm import sessionmaker


Base.metadata.create_all(engine) # 创建表
Session = sessionmaker() # 创建Session类
session = Session(bind=engine) # 实例化Session

user = User()
user.name = 'name1'

forum1 = Forum(
    name='forum_name1',
    sender=user # 定义forum1的发送者是user
)

forum2 = Forum()
forum2.name = 'forum_name2'
user.send_forums.append(forum2) # 通过user,定义user发送了forum2

session.add(user) # 因为user和forum1和forum2都有关系,仅仅保存user,就可以一起维护了相关联的forum1和forum2
session.commit() # 提交数据

user1 = session.query(User).filter_by(name='name1').first() 
for forum in user1.send_forums: # 打印name='name1'用户发送的forum的name
    print(forum.name)

forum = session.query(Forum).filter_by(name='forum_name1').first() 
print(forum.sender.name) # 打印name='forum_name1'的forum它的发送者user
session.close()

猜你喜欢

转载自blog.csdn.net/kzl_knight/article/details/103097893