深圳企业建站模板,陕西手机网站建设公司哪家好,网站被人恶意刷流量,app网站建站系统SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门 本章内容#xff0c;稍微有… SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门 本章内容稍微有些复杂建议腾出2小时空闲时间冲杯咖啡或泡杯茶 , 慢慢看在电脑上跑下代码可以加深理解. 六、表间关系的定义与CRUD操作
表间关系主要包括一对多一对一多对多。其中一对多关系中也隐含了多对一关系。 表间关系是数据库操作中的重要技术点非常有必要理解与掌握。
1、 一对多表间关系的定义
一对多表间关系实现语法
以一对多关系为例
子表侧与父表是一对多关系父表侧可以反向查询子表数据与子表是多对一关系。
class Parent(Base):__tablename__ parent_tableid: Mapped[int] mapped_column(primary_keyTrue)children: Mapped[List[Child]] relationship(back_populatesparent)class Child(Base):__tablename__ child_tableid: Mapped[int] mapped_column(primary_keyTrue)parent_id: Mapped[int] mapped_column(ForeignKey(parent_table.id))parent: Mapped[Parent] relationship(back_populateschildren)说明 1在子表中添加外键字段以及relationship()引用 2在父表中添加relationship()引用用于反向查询。
示例代码
父表company, 子表 person, 表结构类定义如下。
from sqlalchemy.orm import DeclarativeBase, Session
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.orm import relationship
from sqlalchemy import ForeignKey
from sqlalchemy import String, Integer
from typing import Listclass Base(DeclarativeBase):pass
class Company(Base):__tablename__ companyid: Mapped[int] mapped_column(Integer, primary_keyTrue)company_name: Mapped[str] mapped_column(String(30), indexTrue)persons: Mapped[List[Person]] relationship(back_populatescompany, cascadeall, delete-orphan)def __repr__(self) - str:return fCompany(id{self.id}, company_name{self.company_name})class Person(Base):__tablename__ personid: Mapped[int] mapped_column(Integer, primary_keyTrue)name: Mapped[str] mapped_column(String(30))age: Mapped[int] mapped_column(Integer)company_id: Mapped[int] mapped_column(ForeignKey(company.id))company: Mapped[Company] relationship(back_populatespersons)def __repr__(self) - str:return fPerson(id{self.id}, name{self.name})说明 1从子表视角看1个人只属于1个Company; 但1个Company 对应多个人因此在父表则relationship() 左侧的类型注解为 List[‘Person’], 也可以用Set[‘Person’] 2父表中添加删除依赖cascade“all, delete-orphan”即子表中不存在对父表记录的引用时才能删除以保证数据的完整性。 3当前版本可能存在bug, 官方文档中的示例中有的字段使用简化写法右侧未给出mapped_column())sqlite3运行是没有问题的但mysql, postgresql创建表时会丢弃简化写法的字段导致后续insert等操作失败。 因此请严格请勿采有简化写法。
多对一关系的实现语法
当不需要反向查询时则父表与子表形成Many to One 多对一关系 在父表则添加子表的外键与relationship()引用子表无须做额外配置
class Parent(Base):__tablename__ parent_tableid: Mapped[int] mapped_column(primary_keyTrue)child_id: Mapped[int] mapped_column(ForeignKey(child_table.id))child: Mapped[Child] relationship()class Child(Base):__tablename__ child_tableid: Mapped[int] mapped_column(primary_keyTrue)如果允许 child_id空值则将改字段的类型注解修改为
from typing import Optional
......
child_id: Mapped[Optional[int]] mapped_column(ForeignKey(child_table.id))对于3.10版本类型注解支持 | 操作符
child_id: Mapped[int | None] mapped_column(ForeignKey(child_table.id))
child: Mapped[Child | None] relationship(back_populatesparents)2、 插入数据与多表联合查询
1在数据库创建表
# 创建数据库连接引擎对象
engine create_engine(mysqlmysqlconnector://root:Admin123localhost:3306/testdb)
# 将DDL语句映射到数据库表如果数据库表不存在则创建该表
Base.metadata.create_all(engine)
# 打印创建创建的表
Print(Base.metadata.tables) 2插入数据
基本步骤包括
(1)为测试方便先写1个get_or_create()函数如果插入对象在数据库中已存在则不插入以方便连续测试。 (2)创建session对象 (3)先创建父表对象并插入 (4)创建子表对象并插入 (5)用多表查询方法检查结果
Step-1: 自定义create_or_create()函数
官方提供的upsert方法不通用。下面函数是通用的
def get_or_create(session, model, defaultsNone, **kwargs):如果不存在则创建如果存在则返回输入参数session: sqlalchemy sessionmodel: 自定义的ORM类defaults: 有默认值的字段kwargs: 其他字段(必须包含主要字段)返回值instance: 返回的实例instance session.query(model).filter_by(**kwargs).first()if instance:print(instance already exists, instance)return instanceelse:params dict((k, v) for k, v in kwargs.items()if not isinstance(v, ClauseElement))if defaults:params.update(defaults)instance model(**params)session.add(instance)session.commit()print(instance inserted, instance)return instanceStep-2: 向两个关联表插入数据
用with 语句创建session对象插入操作顺序先父表再子表
with Session(engine) as session:# 插入数据get_or_create(session, Company, company_name蜀汉)get_or_create(session, Company, company_name曹魏)get_or_create(session, Company, company_name东吴)stmt select(Company)results session.scalars(stmt)print(results.all())# insert data in person tablecompany_shu session.scalars(select(Company).where(Company.company_name 蜀汉)).first()get_or_create(session, Person, name刘备,age42, companycompany_shu)get_or_create(session, Person, name关羽,age40, companycompany_shu)get_or_create(session, Person, name张飞, age38, companycompany_shu)company_wei session.scalars(select(Company).where(Company.company_name 曹魏)).first()get_or_create(session, Person, name张辽, age40, companycompany_wei)get_or_create(session, Person, name曹操, age38, companycompany_wei)company_wu session.scalars(select(Company).where(Company.company_name 东吴)).first()get_or_create(session, Person, name周瑜, age30, companycompany_wu)3) 多表联合查询 # select with Join 多表查询stmt select(Person).join(Person.company).where(Company.company_name 蜀汉).order_by(Person.age)results session.scalars(stmt)# 遍历结果for r in results:print(r.name, r.age, r.company.company_name)Output:
instance inserted Company(id1, company_name蜀汉)
instance inserted Company(id2, company_name曹魏)
instance inserted Company(id3, company_name东吴)
[Company(id1, company_name蜀汉), Company(id2, company_name曹魏), Company(id3, company_name东吴)]
instance inserted Person(id1, name刘备)
instance inserted Person(id2, name关羽)
instance inserted Person(id3, name张飞)
instance inserted Person(id4, name张辽)
instance inserted Person(id5, name曹操)
instance inserted Person(id6, name周瑜)
张飞 38 蜀汉
关羽 40 蜀汉
刘备 42 蜀汉删除数据 当删除父表记录时子表中应无对此数据的引用否则无法删除。
3、 一对一关系
从外键角度看一对一关系也是一对多关系。实现时
在父表中收集子表数据时类型注解不使用集合类型即可。子表中relationship()方法中添加single_parentTrue.
class Parent(Base):__tablename__ parent_tableid: Mapped[int] mapped_column(primary_keyTrue)
child: Mapped[Child] relationship(back_populatesparent) # 一对多时使用child: Mapped[List[Child]] class Child(Base):__tablename__ child_tableid: Mapped[int] mapped_column(primary_keyTrue)parent_id: Mapped[int] mapped_column(ForeignKey(parent_table.id))parent: Mapped[Parent] relationship(back_populateschildsingle_parentTrue)4、 多对多关系
多对多关系特点 1父表与子表子表与父表之间均为多对多关系。 2通常使用1张中间表 与父表、子表均实现1对多关系。 当然有的ORM模型将中间表的创建隐藏起来但在数据库中还是可以看到
多对多关系定义示例
from __future__ import annotationsfrom sqlalchemy import Column
from sqlalchemy import Table
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import relationshipclass Base(DeclarativeBase):pass# note for a Core table, we use the sqlalchemy.Column construct,
# not sqlalchemy.orm.mapped_column
association_table Table(association_table,Base.metadata,Column(left_id, ForeignKey(left_table.id)),Column(right_id, ForeignKey(right_table.id)),
)class Parent(Base):__tablename__ left_tableid: Mapped[int] mapped_column(primary_keyTrue)children: Mapped[List[Child]] relationship(secondaryassociation_table, back_populatesparents)class Child(Base):__tablename__ right_tableid: Mapped[int] mapped_column(primary_keyTrue)parents: Mapped[List[Parent]] relationship(secondaryassociation_table, back_populateschildren)多对多关系的查询、插入操作与一对多查询相似。 需要注意的是删除操作。
从多对多关系中删除数据
用SQL来实现时需要先从父表与子表删除数据再从中间表删除。ORM API 可以自动完成这个过程。 如要删除子表的某条记录。
myparent.children.remove(somechild)注通过session.delete(somechild)时MySql可能会报错我遇到的原因有多种不建议使用。 同样如果要删除父表中的1条记录
mychild.parent.remove(someparent)
文章转载自: http://www.morning.rcyrm.cn.gov.cn.rcyrm.cn http://www.morning.qkgwz.cn.gov.cn.qkgwz.cn http://www.morning.baohum.com.gov.cn.baohum.com http://www.morning.jhfkr.cn.gov.cn.jhfkr.cn http://www.morning.mmhaoma.com.gov.cn.mmhaoma.com http://www.morning.chzqy.cn.gov.cn.chzqy.cn http://www.morning.zmyzt.cn.gov.cn.zmyzt.cn http://www.morning.ryjl.cn.gov.cn.ryjl.cn http://www.morning.yggdq.cn.gov.cn.yggdq.cn http://www.morning.rqfkh.cn.gov.cn.rqfkh.cn http://www.morning.mjmtm.cn.gov.cn.mjmtm.cn http://www.morning.nlbw.cn.gov.cn.nlbw.cn http://www.morning.qxjck.cn.gov.cn.qxjck.cn http://www.morning.cndxl.cn.gov.cn.cndxl.cn http://www.morning.bsrqy.cn.gov.cn.bsrqy.cn http://www.morning.yqyhr.cn.gov.cn.yqyhr.cn http://www.morning.zwdrz.cn.gov.cn.zwdrz.cn http://www.morning.fygbq.cn.gov.cn.fygbq.cn http://www.morning.rxfbf.cn.gov.cn.rxfbf.cn http://www.morning.ktmbp.cn.gov.cn.ktmbp.cn http://www.morning.skfkx.cn.gov.cn.skfkx.cn http://www.morning.wrtsm.cn.gov.cn.wrtsm.cn http://www.morning.qzxb.cn.gov.cn.qzxb.cn http://www.morning.pwppk.cn.gov.cn.pwppk.cn http://www.morning.sbrpz.cn.gov.cn.sbrpz.cn http://www.morning.plfrk.cn.gov.cn.plfrk.cn http://www.morning.rtqyy.cn.gov.cn.rtqyy.cn http://www.morning.mfrb.cn.gov.cn.mfrb.cn http://www.morning.dwrjj.cn.gov.cn.dwrjj.cn http://www.morning.wkjzt.cn.gov.cn.wkjzt.cn http://www.morning.phxns.cn.gov.cn.phxns.cn http://www.morning.yxshp.cn.gov.cn.yxshp.cn http://www.morning.lmqw.cn.gov.cn.lmqw.cn http://www.morning.pwrkl.cn.gov.cn.pwrkl.cn http://www.morning.sqqhd.cn.gov.cn.sqqhd.cn http://www.morning.dqpnd.cn.gov.cn.dqpnd.cn http://www.morning.ppwdh.cn.gov.cn.ppwdh.cn http://www.morning.fhqdb.cn.gov.cn.fhqdb.cn http://www.morning.brwnd.cn.gov.cn.brwnd.cn http://www.morning.bxch.cn.gov.cn.bxch.cn http://www.morning.skwwj.cn.gov.cn.skwwj.cn http://www.morning.c7500.cn.gov.cn.c7500.cn http://www.morning.rcrfz.cn.gov.cn.rcrfz.cn http://www.morning.nyqnk.cn.gov.cn.nyqnk.cn http://www.morning.cbnxq.cn.gov.cn.cbnxq.cn http://www.morning.lzqdl.cn.gov.cn.lzqdl.cn http://www.morning.qsmch.cn.gov.cn.qsmch.cn http://www.morning.hncrc.cn.gov.cn.hncrc.cn http://www.morning.nbfkk.cn.gov.cn.nbfkk.cn http://www.morning.kyctc.cn.gov.cn.kyctc.cn http://www.morning.gchqy.cn.gov.cn.gchqy.cn http://www.morning.fglth.cn.gov.cn.fglth.cn http://www.morning.wwkft.cn.gov.cn.wwkft.cn http://www.morning.gczqt.cn.gov.cn.gczqt.cn http://www.morning.qglqb.cn.gov.cn.qglqb.cn http://www.morning.zpfqh.cn.gov.cn.zpfqh.cn http://www.morning.pcjw.cn.gov.cn.pcjw.cn http://www.morning.ztmkg.cn.gov.cn.ztmkg.cn http://www.morning.tyjnr.cn.gov.cn.tyjnr.cn http://www.morning.ypcbm.cn.gov.cn.ypcbm.cn http://www.morning.drfrm.cn.gov.cn.drfrm.cn http://www.morning.txrq.cn.gov.cn.txrq.cn http://www.morning.kaakyy.com.gov.cn.kaakyy.com http://www.morning.rpzqk.cn.gov.cn.rpzqk.cn http://www.morning.kwcnf.cn.gov.cn.kwcnf.cn http://www.morning.xxknq.cn.gov.cn.xxknq.cn http://www.morning.hrdx.cn.gov.cn.hrdx.cn http://www.morning.gmgyt.cn.gov.cn.gmgyt.cn http://www.morning.mngh.cn.gov.cn.mngh.cn http://www.morning.wwwghs.com.gov.cn.wwwghs.com http://www.morning.bkkgt.cn.gov.cn.bkkgt.cn http://www.morning.dyrzm.cn.gov.cn.dyrzm.cn http://www.morning.tqsmg.cn.gov.cn.tqsmg.cn http://www.morning.jzccn.cn.gov.cn.jzccn.cn http://www.morning.hslgq.cn.gov.cn.hslgq.cn http://www.morning.ycwym.cn.gov.cn.ycwym.cn http://www.morning.bzsqr.cn.gov.cn.bzsqr.cn http://www.morning.zrkws.cn.gov.cn.zrkws.cn http://www.morning.lxkhx.cn.gov.cn.lxkhx.cn http://www.morning.lmzpk.cn.gov.cn.lmzpk.cn