首页 > 数据库 >[sqlAlchemy] sqlAlchemy中的relationship()

[sqlAlchemy] sqlAlchemy中的relationship()

时间:2024-01-25 20:34:59浏览次数:30  
标签:__ sqlAlchemy addresses relationship User Address id user

在学习select和join的时候被relationship相关的东西搞得头大, 感觉看不懂这个就没办法继续下去了
官方教程在这里
先把我们一直在用的两个类拿过来
用户类, 对应user_account表

class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(30))
    fullname: Mapped[Optional[str]]
    addresses: Mapped[List["Address"]] = relationship(back_populates="user")
    def __repr__(self) -> str:
        return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"

地址类, 对应addresses表; 注意这里是一对多的关系, 即一个用户可以有多个地址

class Address(Base):
    __tablename__ = "address"
    id: Mapped[int] = mapped_column(primary_key=True)
    email_address: Mapped[str]
    user_id = mapped_column(ForeignKey("user_account.id"))
    user: Mapped[User] = relationship(back_populates="addresses")
    def __repr__(self) -> str:
        return f"Address(id={self.id!r}, email_address={self.email_address!r})"

有两个东西

  1. ForeignKey, 指定一个外键, 将user_account和addresses连接, 以将Address.user_id和user_account表中的主键绑定的方式
  2. relationship(), 即Address.user属性将整表连接至User类, 而链接的另一边则要放在User类里, 即User.addresses属性的由来
# User类: addresses是一个Address对象的数组, 绑定了Address类的user属性
addresses: Mapped[List["Address"]] = relationship(back_populates="user")

# Address类: user是一个User对象, 绑定了User类的addresses
user: Mapped[User] = relationship(back_populates="addresses")

这样, orm就可以自动连接两张表了, 在Address这边, Address.user属性指向User的一个实例; 在User这边, User.address属性指向一堆Address的实例。

在relationship()的帮助下, 当我们更新User的数据时, Address也会经由User.addresses进行更新
首先创建一个用户对象, 不指明addresses, 因此为空集

spongebob = User(name="spongebob", fullname="Spongebob Squarepants")
# id会被自动指定

接着我们更新addresses

spongebob.addresses = [
  Address(email_address="[email protected]"), 
  Address(email_address="[email protected]")
]
# id自动更新, user_id是外键, user是被relationship()绑定的

这样我们可以在User类访问Address的对象

spongebob.addresses[1]

以及在Address类中访问User

spongebob.addresses[1].user

使用commit()提交后, User和Address都会被提交
注意当我们使用s = select(User).where(User.name=="spongebob")返回User数据时, addresses不会被返回

[<User(id=1, name='spongebob', fullname='Spongebob Squarepants')>]

只有当你进行查询spongebob.addresses时, 才会加载

[ <Address(email_address="[email protected]")>, 
  <Address(email_address="[email protected]")> ]

以上我们说的都是one-to-many情况, 而在many-to-many的情况中, 则还需要一个参数secondary,以及一个核心表关于many-to-many

from __future__ import annotations

class Base(DeclarativeBase):
    pass

# 对于一个核心表来说, 应该使用Column, 而不是mapped_column
association_table = Table(
    "association_table",
    Base.metadata,
    Column("left_id", ForeignKey("left_table.id"), primary_key=True),
    Column("right_id", ForeignKey("right_table.id"), primary_key=True),
)


class Parent(Base):
    __tablename__ = "left_table"

    id: Mapped[int] = mapped_column(primary_key=True)
    children: Mapped[List[Child]] = relationship(secondary=association_table, back_populates="parents")

class Child(Base):
    __tablename__ = "right_table"

    id: Mapped[int] = mapped_column(primary_key=True)
    parents: Mapped[List[Parent]] = relationship(secondary=association_table, back_populates="children")

这里就大概梳理了一下relationship()是干嘛的以及怎么写,具体的细节还是要去看官方文档

标签:__,sqlAlchemy,addresses,relationship,User,Address,id,user
From: https://www.cnblogs.com/Akira300000/p/17987463

相关文章

  • [SQLAlchemy] sqlAlchemy学习笔记(2): 在orm中使用select
    SELECT的作用select在sql中的作用是选中特定列并以表的形式返回,是必要的关键字;在sqlalchemy中,select()方法会返回一个Select对象,并根据这个对象引入其他方法,如where(),join(),order_by()等等fromsqlalchemyimportselectstmt=select(User).where(User.name==......
  • [SQLAlchemy] SQLAlchemy学习笔记: 基础使用
    InstallationpipinstallSQLAlchemymakesurethatissql-alchemy2创建引擎数据库url格式一般为dialect+driver://username:password@host:port/database#PyMySQL-python里的数据库驱动engine=create_engine("mysql+pymysql://scott:tiger@localhost/foo?charset=utf......
  • FlaskSQLAlchemy中的Pagination类型对象
    FlaskSQLAlchemy中的Pagination类型对象。一个Query对象调用paginate方法就获得了Pagination对象。paginate方法传入了两个参数,一个是当前页,另一个是每一页最多显示多少博客。paginate的返回值为代表当前页的Pagination对象。一个Paginationi对象的常用属性有:items当前页面中的......
  • 基于SQLAlchemy的模型,它不一定需要​​__init__​​​函数
    这个User类是一个基于SQLAlchemy的模型,它不一定需要__init__函数。SQLAlchemy会自动为你的模型创建一个默认的__init__函数,你可以直接创建对象,如user=User(id=1,name='username')。但是,如果你需要在创建对象时执行一些自定义操作,你可以提供自己的__init__函数。例如:classUser(d......
  • SQLAlchemy scoped_session
    SQLAlchemyscoped_session本身session不是线程安全的。 https://docs.sqlalchemy.org/en/14/orm/contextual.htmlTheobjectisthescoped_sessionobject,anditrepresentsaregistryofSessionobjects.Ifyou’renotfamiliarwiththeregistrypattern,ago......
  • sqlalchemy 实现 mysql INSERT INTO...ON DUPLICATE KEY UPDATE语法
    1.前言myql的INSERTINTO...ONDUPLICATEKEYUPDATE语句,简单点来说,就是如果记录不存在,则插入,如果记录存在,则更新。那怎么判断记录存在否?——主键、唯一键。那不是可以使用replace语句吗?——原理上可以,但是sqlalchemyorm中的的实现,是使用merge语法,这个语法有一个限制,就是判......
  • 大白话说Python+Flask入门(六)Flask SQLAlchemy操作mysql数据库
    写在前面这篇文章被搁置真的太久了,不知不觉拖到了周三了,当然,也算跟falsk系列说再见的时候,真没什么好神秘的,就是个数据库操作,就大家都知道的CRUD吧。FlaskSQLAlchemy的使用1、FlaskSQLAlchemy简介FlaskSQLAlchemy是基于Flaskweb框架和SQLAlchemyORM(对象关系映射)的工具......
  • Flask-SQLALchemy
    SQLALchemyorm,对象-关系映射,主要实现模型对象到关系型数据库的映射,orm提供一种面向对象的数据库的方式给开发者,不需要编写原生的sql语句也能操作数据库,实现了业务代码与底层数据的解耦优势:1.对数据库操作转为对类/对象的属性和方法的操作,字段--对象数据,sql关键字--操作方法......
  • 【Python/数据库】SQLAlchemy基础操作
    一、SQLAlchemy——创建表#ORM#1.Class-Obj#2.创建数据库引擎#3.将所有的Class序列化为数据表#4.ORM操作-CRUD(增删改查操作的简称)1.创建一个class#create_table.pyfromsqlalchemy.ext.declarativeimportdeclarative_baseBase=declarative_base......
  • 【Python/数据库】SQLAlchemy一对多,多对多操作
    SQLAlchemy一对多操作1.创建多表#create_table_ForeginKey.pyfromsqlalchemy.ext.declarativeimportdeclarative_basefromsalalchemyimportColumn,INT,VARCHAR,ForeignKeyfromsqlalchemyimportcreate_engineBase=declarative_base()classStudent(Base)......