sqlalchemy的relationship

0 阅读2分钟

介绍

为了学习sqlalchemy的基本概念,我们使用简单的模型来描述relationship的功能

数据模型

用户和地址,一个用户可以有多个地址,一个地址对应一个用户

案例代码

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

# 创建基类
Base = declarative_base()

# User 模型
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    # 定义与 Address 模型的关系
    addresses = relationship("Address", back_populates="user")

# Address 模型
class Address(Base):
    __tablename__ = 'addresses'
    id = Column(Integer, primary_key=True)
    email = Column(String)
    user_id = Column(Integer, ForeignKey('users.id'))
    # 定义反向关联的属性
    user = relationship("User", back_populates="addresses")

# 创建数据库引擎和会话
engine = create_engine('sqlite:///test.db')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# 创建一个用户和地址
user = User(name='John')
address1 = Address(email='john@example.com', user=user)
address2 = Address(email='john2@.com', user=user)

# 将对象添加到会话并提交
session.add(user)
session.add(address1)
session.add(address2)
session.commit()

# 从用户访问地址
print("从用户访问地址:")
for address in user.addresses:
    print(address.email)

# 从地址访问用户
print("从地址访问用户:")
print(address1.user.name)

session.close()

效果截图

下面的图片可以看出,当访问user这个对象时,我们可以看到他的多个地址;访问地址时我们可以根据地址找到对应的用户

image.png 下面我们来看一下具体的在数据库中,这样的数据是如何存储的

image.png 首先在user表中,我们只看到了一个用户John,并没有其他的属性

image.png 接下来我们看address表,我们可以看到有两个地址,其中的user_id均指向了John这个用户

总结

上面的几张图片可以展示出数据库层的存储方式以及应用层的使用方式,sqlalchemy可以直接用对象的方式去访问多个复杂的关系和对象,而在底层的SQL存储结构却并不表现这些复杂的relationship关系,这说明sqlalchemy orm关系框架中给我们做了很多事情,我们可以通过调试模式看到sqlalchemy具体执行了哪些SQL语句:

image.png