做微信公众号网站,广东建设企业网站怎么样,中山做网站哪家便宜,网络推广公司运作随记 最近在使用 SQLAlchemy 2.0 的过程中#xff0c;有一些不适应的地方#xff0c;所以想梳理一下 SQLAlchemy ORM 的使用。 关于旧版的使用以及其他信息请参考另一篇文章Flask 初探七, 这里就不过多赘述#xff0c;直接进入主题。 One To Many
单向
官方版本 class Par…随记 最近在使用 SQLAlchemy 2.0 的过程中有一些不适应的地方所以想梳理一下 SQLAlchemy ORM 的使用。 关于旧版的使用以及其他信息请参考另一篇文章Flask 初探七, 这里就不过多赘述直接进入主题。 One To Many
单向
官方版本 class Parent(Base):__tablename__ parent_tableid: Mapped[int] mapped_column(primary_keyTrue)# TODO relationship()# Parent -- Childchildren: Mapped[List[Child]] relationship()class Child(Base):__tablename__ child_tableid: Mapped[int] mapped_column(primary_keyTrue)parent_id: Mapped[int] mapped_column(ForeignKey(parent_table.id))
CompanyToApp class CompanyInfoModel(db.Model):__tablename__ company_info__table_args__ {comment: 公司表}code mapped_column(String(200), comment公司编码, nullableFalse, indexTrue)name mapped_column(String(200), comment公司名, nullableFalse, indexTrue)detail mapped_column(String(500), comment描述, default, nullableFalse)# 官方版本使用 Mapped[List[AppInfoModel]] 指定类型# app:Mapped[List[AppInfoModel]] relationship(back_populatescompany)# 为了和上面的code、name 形式同一我使用了下面这种方式# TODO 单向绑定 company -- appapp relationship(AppInfoModel)class AppInfoModel(db.Model):__tablename__ app_info__table_args__ {comment: 应用表}name mapped_column(String(100), comment应用名, nullableFalse, indexTrue)secret mapped_column(String(200), commentsecret, nullableFalse, indexTrue)detail mapped_column(String(500), comment描述, default, nullableFalse)# 官方版本# company_id:Mapped[BIGINT] mapped_column(ForeignKey(company_info.id), indexTrue)# 单向绑定 或者 双向绑定ForeignKey 是不变的company_id mapped_column(BIGINT, ForeignKey(company_info.id), indexTrue)
双向
官方版本 class Parent(Base):__tablename__ parent_tableid: Mapped[int] mapped_column(primary_keyTrue)# TODO relationship(back_populatesparent)# 双向绑定在 Parent 使用 back_populates 指定 Child 的属性 parentchildren: Mapped[List[Child]] relationship(back_populatesparent)class Child(Base):__tablename__ child_tableid: Mapped[int] mapped_column(primary_keyTrue)# ForeignKey 是不变的parent_id: Mapped[int] mapped_column(ForeignKey(parent_table.id))# 双向绑定在 Child 增加 Parent 类型的属性 parent 通过 back_populates 关联 childrenparent: Mapped[Parent] relationship(back_populateschildren)CompanyToApp class CompanyInfoModel(db.Model):__tablename__ company_info__table_args__ {comment: 公司表}code mapped_column(String(200), comment公司编码, nullableFalse, indexTrue)name mapped_column(String(200), comment公司名, nullableFalse, indexTrue)detail mapped_column(String(500), comment描述, default, nullableFalse)# 双向绑定app relationship(AppInfoModel, back_populatescompany)class AppInfoModel(db.Model):__tablename__ app_info__table_args__ {comment: 应用表}name mapped_column(String(100), comment应用名, nullableFalse, indexTrue)secret mapped_column(String(200), commentsecret, nullableFalse, indexTrue)detail mapped_column(String(500), comment描述, default, nullableFalse) # 单向绑定 或者 双向绑定ForeignKey 是不变的company_id mapped_column(BIGINT, ForeignKey(company_info.id), indexTrue)# 双向绑定company relationship(CompanyInfoModel, back_populatesapp)
小结
ForeignKey 在多的一方不管单向还是双向 ForeignKey 都是必须的单向绑定多的一方使用 relationship 即可双向绑定需要 relationship back_populates双向绑定 在类 CompanyInfoModel 增加类型为 AppInfoModel 的属性 app在类 AppInfoModel 增加类型为 CompanyInfoModel 的属性 company使用 back_populates 指向关联类的 关联属性 CompanyInfoModel.app -- AppInfoModel.company -- CompanyInfoModelAppInfoModel.company -- CompanyInfoModel.app AppInfoModel
Many To Many 间接
间接单向
官方 from typing import Optionalfrom 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):passclass Association(Base):__tablename__ association_tableleft_id: Mapped[int] mapped_column(ForeignKey(left_table.id), primary_keyTrue)right_id: Mapped[int] mapped_column(ForeignKey(right_table.id), primary_keyTrue)extra_data: Mapped[Optional[str]]child: Mapped[Child] relationship()class Parent(Base):__tablename__ left_tableid: Mapped[int] mapped_column(primary_keyTrue)children: Mapped[List[Association]] relationship()class Child(Base):__tablename__ right_tableid: Mapped[int] mapped_column(primary_keyTrue)
UserGroup2User class UserUserGroupRelateModel(db.Model):__tablename__ user_usergroup_relate__table_args__ {comment: User_UserGroup_关联表}user_id mapped_column(ForeignKey(user_info.id), primary_keyTrue, indexTrue)user_group_id mapped_column(ForeignKey(user_group_info.id), primary_keyTrue, indexTrue) # 多对多 单向 官方# relate_user:Mapped[List[UserInfoModel]] relationship()# 多对多 单向 UserUserGroupRelateModel.relate_user 是 UserInfoModel 类型# UserGroupInfoModel.users_relate -- UserUserGroupRelateModel.relate_user -- UserInfoModelrelate_user relationship(UserInfoModel)class UserGroupInfoModel(db.Model):__tablename__ user_group_info__table_args__ {comment: 用户组表}name mapped_column(String(100), comment用户组 组名, nullableFalse, indexTrue) # 多对多 间接 单向 官方# users_relate:Mapped[List[UserUserGroupRelateModel]] relationship()# 多对多 单向 UserGroupInfoModel.users_relate 是 UserUserGroupRelateModel 类型# UserGroupInfoModel.users_relate -- UserUserGroupRelateModel.relate_user -- UserInfoModelusers_relate relationship(UserUserGroupRelateModel)class UserInfoModel(db.Model):__tablename__ user_info__table_args__ {comment: 用户表}code mapped_column(String(200), comment用户编码, nullableFalse, indexTrue)name mapped_column(String(100), comment用户名, nullableFalse, indexTrue)phone mapped_column(String(100), comment手机号, nullableFalse, default)email mapped_column(String(100), comment电子邮件, nullableFalse, default)
间接双向
官方
from typing import Optionalfrom 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):passclass Association(Base):__tablename__ association_tableleft_id: Mapped[int] mapped_column(ForeignKey(left_table.id), primary_keyTrue)right_id: Mapped[int] mapped_column(ForeignKey(right_table.id), primary_keyTrue)extra_data: Mapped[Optional[str]]child: Mapped[Child] relationship(back_populatesparents)parent: Mapped[Parent] relationship(back_populateschildren)class Parent(Base):__tablename__ left_tableid: Mapped[int] mapped_column(primary_keyTrue)children: Mapped[List[Association]] relationship(back_populatesparent)class Child(Base):__tablename__ right_tableid: Mapped[int] mapped_column(primary_keyTrue)parents: Mapped[List[Association]] relationship(back_populateschild)
UserGroup2User
class UserUserGroupRelateModel(db.Model):__tablename__ user_usergroup_relate__table_args__ {comment: User_UserGroup_关联表}user_id mapped_column(ForeignKey(user_info.id), primary_keyTrue, indexTrue)user_group_id mapped_column(ForeignKey(user_group_info.id), primary_keyTrue, indexTrue) # 多对多 间接双向 官方# relate_user:Mapped[UserInfoModel] relationship(back_populatesgroups_relate)# relate_user_group:Mapped[UserGroupInfoModel] relationship(back_populatesusers_relate) # 多对多 间接单向 UserUserGroupRelateModel.relate_user 是 UserInfoModel 类型relate_user relationship(UserInfoModel, back_populatesgroups_relate)relate_user_group relationship(UserGroupInfoModel, back_populatesusers_relate)class UserGroupInfoModel(db.Model):__tablename__ user_group_info__table_args__ {comment: 用户组表}name mapped_column(String(100), comment用户组 组名, nullableFalse, indexTrue) # 多对多 间接双向 官方# users_relate:Mapped[List[UserUserGroupRelateModel]] relationship(back_populatesrelate_user_group)# 多对多 间接双向 # 间接双向 约等于 两个单向# UserGroupInfoModel.users_relate 是 UserUserGroupRelateModel 类型# UserUserGroupRelateModel.relate_user_group 是 UserGroupInfoModel 类型# UserGroupInfoModel.users_relate -- UserUserGroupRelateModel.relate_user_group -- UserGroupInfoModelusers_relate relationship(UserUserGroupRelateModel, back_populatesrelate_user_group)class UserInfoModel(db.Model):__tablename__ user_info__table_args__ {comment: 用户表}code mapped_column(String(200), comment用户编码, nullableFalse, indexTrue)name mapped_column(String(100), comment用户名, nullableFalse, indexTrue)phone mapped_column(String(100), comment手机号, nullableFalse, default)email mapped_column(String(100), comment电子邮件, nullableFalse, default)# 多对多 间接双向 官方# groups_relate:Mapped[List[UserUserGroupRelateModel]] relationship(back_populatesrelate_user)# 多对多 间接双向 # 间接双向 约等于 两个单向# UserInfoModel.groups_relate 是 UserUserGroupRelateModel 类型# UserUserGroupRelateModel.relate_user 是 UserInfoModel 类型# UserInfoModel.groups_relate -- UserUserGroupRelateModel.relate_user -- UserInfoModelgroups_relate relationship(UserUserGroupRelateModel, back_populatesrelate_user)
间接关联对象 小结
多对多需要借助第三方 UserUserGroupRelateModel单向只需要 relationship双向需要 relationship back_populates多对多的单向单向只需要 relationship 在类 UserGroupInfoModel 增加类型为 UserUserGroupRelateModel 的属性 users_relate在类 UserUserGroupRelateModel 增加类型为 UserInfoModel 的属性 relate_userUserGroupInfoModel.users_relate -- UserUserGroupRelateModel.relate_user --UserInfoModel 多对多的双向 UserGroupInfoModel.users_relate -- UserUserGroupRelateModel.relate_user -- UserInfoModel 在类 UserGroupInfoModel 增加类型为 UserUserGroupRelateModel 的属性 users_relate在类 UserUserGroupRelateModel 增加类型为 UserInfoModel 的属性 relate_user UserInfoModel.groups_relate -- UserUserGroupRelateModel.relate_user_group -- UserGroupInfoModel 在类 UserInfoModel 增加类型为 UserUserGroupRelateModel 的属性 groups_relate在类 UserUserGroupRelateModel 增加类型为 UserGroupInfoModel 的属性 relate_user_group 通过 back_populates 关联对应类型的 关联属性 UserGroupInfoModel.users_relate -- UserUserGroupRelateModel.relate_user_group -- UserGroupInfoModel 类 UserGroupInfoModel的属性 users_relate 是 UserUserGroupRelateModel 类型类 UserUserGroupRelateModel的属性 relate_user_group 是 UserGroupInfoModel 类型 UserInfoModel.groups_relate -- UserUserGroupRelateModel.relate_user -- UserInfoModel 类 UserInfoModel的属性 groups_relate 是 UserUserGroupRelateModel 类型类 UserUserGroupRelateModel的属性 relate_user 是 UserInfoModel 类型
Many To Many 间接 直接
Many To Many 直接 class UserUserGroupRelateModel(db.Model):__tablename__ user_usergroup_relate__table_args__ {comment: User_UserGroup_关联表}user_id mapped_column(ForeignKey(user_info.id), primary_keyTrue, indexTrue)user_group_id mapped_column(ForeignKey(user_group_info.id), primary_keyTrue, indexTrue) class UserGroupInfoModel(db.Model):__tablename__ user_group_info__table_args__ {comment: 用户组表}name mapped_column(String(100), comment用户组 组名, nullableFalse, indexTrue) # # 多对多 双向绑定 官方# user:Mapped[List[UserInfoModel]] relationship(secondaryuser_usergroup_relate, back_populatesgroup)# 多对多 双向直接user relationship(UserInfoModel,secondaryuser_usergroup_relate, back_populatesgroup)class UserInfoModel(db.Model):__tablename__ user_info__table_args__ {comment: 用户表}code mapped_column(String(200), comment用户编码, nullableFalse, indexTrue)name mapped_column(String(100), comment用户名, nullableFalse, indexTrue)phone mapped_column(String(100), comment手机号, nullableFalse, default)email mapped_column(String(100), comment电子邮件, nullableFalse, default)# # 多对多 双向直接 官方# group:Mapped[List[UserGroupInfoModel]] relationship(secondaryuser_usergroup_relate, back_populatesuser)# 多对多 双向直接group relationship(UserGroupInfoModel, secondaryuser_usergroup_relate, back_populatesuser)
Many To Many 间接直接 class UserUserGroupRelateModel(db.Model):__tablename__ user_usergroup_relate__table_args__ {comment: User_UserGroup_关联表}user_id mapped_column(ForeignKey(user_info.id), primary_keyTrue, indexTrue)user_group_id mapped_column(ForeignKey(user_group_info.id), primary_keyTrue, indexTrue) # 多对多 间接双向 relate_user relationship(UserInfoModel, back_populatesgroups_relate)relate_user_group relationship(UserGroupInfoModel, back_populatesusers_relate)class UserGroupInfoModel(db.Model):__tablename__ user_group_info__table_args__ {comment: 用户组表}name mapped_column(String(100), comment用户组 组名, nullableFalse, indexTrue) # 多对多 间接双向 users_relate relationship(UserUserGroupRelateModel, back_populatesrelate_user_group)# 多对多 双向直接user_list relationship(UserInfoModel,secondaryuser_usergroup_relate, back_populatesgroup_list)class UserInfoModel(db.Model):__tablename__ user_info__table_args__ {comment: 用户表}code mapped_column(String(200), comment用户编码, nullableFalse, indexTrue)name mapped_column(String(100), comment用户名, nullableFalse, indexTrue)phone mapped_column(String(100), comment手机号, nullableFalse, default)email mapped_column(String(100), comment电子邮件, nullableFalse, default)# 多对多 间接双向 groups_relate relationship(UserUserGroupRelateModel, back_populatesrelate_user)# 多对多 双向直接group_list relationship(UserGroupInfoModel, secondaryuser_usergroup_relate, back_populatesuser_list)
小结
直接 或者 间接都必须存在第三方 UserUserGroupRelateModel 直接可以跳过第三方直接关联另一方 UserGroupInfoModel.user_list[0] -- UserInfoModel 类 UserGroupInfoModel的属性 user_list 的每一项都是 UserInfoModel 类型 UserInfoModel.group_list[0] -- UserGroupInfoModel 类 UserInfoModel的属性 group_list 是 UserGroupInfoModel 类型 back_populates 关联另一方的 关联属性 UserGroupInfoModel.user_list back_populates UserInfoModel.group_listUserInfoModel.group_list back_populates UserGroupInfoModel.user_list 间接必须通过第三方才能获取另一方 UserGroupInfoModel.users_relate -- UserUserGroupRelateModel.relate_user -- UserInfoModelUserInfoModel.groups_relate -- UserUserGroupRelateModel.relate_user_group -- UserGroupInfoModel 两者存在冲突即通过直接方式修改的数据在同一个session 里没办法同步到间接反之亦然。 When using this ORM model to make changes, changes made to Parent.children will not be coordinated with changes made to Parent.child_associations or Child.parent_associations in Python; while all of these relationships will continue to function normally by themselves, changes on one will not show up in another until the Session is expired, which normally occurs automatically after Session.commit(). Additionally, if conflicting changes are made, such as adding a new Association object while also appending the same related Child to Parent.children, this will raise integrity errors when the unit of work flush process proceeds. 如果关联对象没有特殊的属性建议选择直接方式 直接方式的 model 只需要在两个多方添加属性访问数据是可以直接跳过 第三方 直接得到另一方的列表 UserGroupInfoModel.user_list避免存在直接间接时可能造成的影响
Source Code 到此结 DragonFangQy 2023.12.25