日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

SQLAlchemy_定义(一对一/一对多/多对多)关系

發(fā)布時(shí)間:2025/4/14 数据库 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SQLAlchemy_定义(一对一/一对多/多对多)关系 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

SQLAlchemy_定義(一對(duì)一/一對(duì)多/多對(duì)多)關(guān)系

  • 目錄
  • Basic?Relationship?Patterns
  • One To Many
  • One To One
  • Many To Many

Basic Relationship Patterns

基本關(guān)系模式?
The imports used for each of the following sections is as follows:?
下列的 import 語(yǔ)句,應(yīng)用到接下來(lái)所有的代章節(jié)中:

?
1 2 3 4 from sqlalchemy import Table, Column, Integer, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base Base = declarative_base()

One To Many

A one to many relationship places a foreign key on the child table referencing the parent.?
表示一對(duì)多的關(guān)系時(shí),在子表類(lèi)中通過(guò) foreign key (外鍵)引用父表類(lèi)。?
relationship()?is then specified on the parent, as referencing a collection of items represented by the child:?
然后,在父表類(lèi)中通過(guò)?relationship()?方法來(lái)引用子表的類(lèi):

?
1 2 3 4 5 6 7 8 9 10 11 class Parent(Base): ????__tablename__ = 'parent' ????id = Column(Integer, primary_key=True) ????children = relationship("Child") ???# 在父表類(lèi)中通過(guò) relationship() 方法來(lái)引用子表的類(lèi)集合 class Child(Base): ????__tablename__ = 'child' ????id = Column(Integer, primary_key=True) ????parent_id = Column(Integer, ForeignKey('parent.id')) ????# 在子表類(lèi)中通過(guò) foreign key (外鍵)引用父表的參考字段

?To establish a bidirectional relationship in one-to-many, where the “reverse” side is a many to one,?
在一對(duì)多的關(guān)系中建立雙向的關(guān)系,這樣的話在對(duì)方看來(lái)這就是一個(gè)多對(duì)一的關(guān)系,?
specify an additional?relationship()?and connect the two using the?relationship.back_populates?parameter:?
在子表類(lèi)中附加一個(gè)?relationship()?方法,并且在雙方的?relationship()?方法中使用?relationship.back_populates?方法參數(shù):

?
1 2 3 4 5 6 7 8 9 10 11 12 class Parent(Base): ????__tablename__ = 'parent' ????id = Column(Integer, primary_key=True) ????children = relationship("Child", back_populates="parent") class Child(Base): ????__tablename__ = 'child' ????id = Column(Integer, primary_key=True) ????parent_id = Column(Integer, ForeignKey('parent.id')) ????parent = relationship("Parent", back_populates="children") ????# 子表類(lèi)中附加一個(gè) relationship() 方法 ????# 并且在(父)子表類(lèi)的 relationship() 方法中使用 relationship.back_populates 參數(shù)

?Child will get a parent attribute with many-to-one semantics.?
這樣的話子表將會(huì)在多對(duì)一的關(guān)系中獲得父表的屬性

Alternatively, the backref option may be used on a single relationship() instead of using back_populates:?
或者,可以在單一的?relationship()?方法中使用?backref?參數(shù)來(lái)代替?back_populates?參數(shù):

?
1 2 3 4 5 6 7 8 9 class Parent(Base): ????__tablename__ = 'parent' ????id = Column(Integer, primary_key=True) ????children = relationship("Child", backref="parent") class Child(Base): ????__tablename__ = 'child' ????id = Column(Integer, primary_key=True) ????parent_id = Column(Integer, ForeignKey('parent.id'))

?

One To One

One To One is essentially a bidirectional relationship with a scalar attribute on both sides.?
一對(duì)一是兩張表之間本質(zhì)上的雙向關(guān)系。?
To achieve this, the uselist flag indicates the placement of a scalar attribute instead of a collection on the “many” side of the relationship.?
要做到這一點(diǎn),只需要在一對(duì)多關(guān)系基礎(chǔ)上的父表中使用?uselist?參數(shù)來(lái)表示。?
To convert one-to-many into one-to-one:

?
1 2 3 4 5 6 7 8 9 10 class Parent(Base): ????__tablename__ = 'parent' ????id = Column(Integer, primary_key=True) ????child = relationship("Child", uselist=False, back_populates="parent") class Child(Base): ????__tablename__ = 'child' ????id = Column(Integer, primary_key=True) ????parent_id = Column(Integer, ForeignKey('parent.id')) ????parent = relationship("Parent", back_populates="child")

?To convert many-to-one into one-to-one:

?
1 2 3 4 5 6 7 8 9 10 class Parent(Base): ????__tablename__ = 'parent' ????id = Column(Integer, primary_key=True) ????child_id = Column(Integer, ForeignKey('child.id')) ????child = relationship("Child", back_populates="parent") class Child(Base): ????__tablename__ = 'child' ????id = Column(Integer, primary_key=True) ????parent = relationship("Parent", back_populates="child", uselist=False)

?As always, the?relationship.backref?and?backref()?functions may be used in lieu of the?relationship.back_populates?approach; to specifyuselist?on a?backref, use the?backref()?function:

同樣的,可以使用下面這種方式:

?
1 2 3 4 5 6 7 8 9 10 11 12 from sqlalchemy.orm import backrefclass Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) child_id = Column(Integer, ForeignKey('child.id')) child = relationship("Child", backref=backref("parent", uselist=False))

Many To Many

Many to Many adds an association table between two classes.?
多對(duì)多關(guān)系會(huì)在兩個(gè)類(lèi)之間增加一個(gè)關(guān)聯(lián)的表。?
The association table is indicated by the?secondary?argument to?relationship().?
這個(gè)關(guān)聯(lián)的表在?relationship()?方法中通過(guò)?secondary?參數(shù)來(lái)表示。?
Usually, the Table uses the MetaData object associated with the declarative base class,?
通常的,這個(gè)表會(huì)通過(guò)?MetaData?對(duì)象來(lái)與聲明基類(lèi)關(guān)聯(lián),?
so that the?ForeignKey?directives can locate the remote tables with which to link:?
所以這個(gè)?ForeignKey?指令會(huì)使用鏈接來(lái)定位到遠(yuǎn)程的表:

定義中間表可以定義中間關(guān)系表相關(guān)的類(lèi),也可以直接通過(guò)Base.metdata生成對(duì)應(yīng)關(guān)系表對(duì)象,不過(guò)基于code first準(zhǔn)則,還是推薦將中間關(guān)系寫(xiě)成類(lèi)。

構(gòu)建第三張關(guān)系類(lèi)實(shí)現(xiàn)多對(duì)多。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 Base = declarative_base() #生成sqlorm基礎(chǔ)類(lèi) class HostUserToGroup(Base): ????__tablename__ = 'hostuser_to_group' # 表名hostuser_to_group ????nid = Column(Integer, primary_key=True,autoincrement=True) ????hostuser_id = Column(Integer,ForeignKey('host_user.id'),primary_key=True)# 外鍵關(guān)聯(lián)host_user表的id字段 ????group_id = Column(Integer,ForeignKey('group.id'),primary_key=True) # 外鍵關(guān)聯(lián)group表的id字段 class UserProfileToGroup(Base): ????__tablename__ = 'userprofile_to_group'# 表名userprofile_to_group ????nid = Column(Integer, primary_key=True,autoincrement=True) ????userprofile_id = Column(Integer,ForeignKey('user_profile.id'),primary_key=True)# 外鍵關(guān)聯(lián)user_profile表的id字段 ????group_id = Column(Integer,ForeignKey('group.id'),primary_key=True)# 外鍵關(guān)聯(lián)group表的id字段 class UserProfileToHostUser(Base): ????__tablename__ = 'userprofile_to_hostuser'# 表名userprofile_to_hostuser ????nid = Column(Integer, primary_key=True,autoincrement=True) ????userprofile_id = Column(Integer,ForeignKey('user_profile.id'),primary_key=True)# 外鍵關(guān)聯(lián)user_profile表的id字段 ????hostuser_id = Column(Integer,ForeignKey('host_user.id'),primary_key=True)# 外鍵關(guān)聯(lián)host_user表的id字段 class Host(Base): ????__tablename__ = 'host' #表名host ????id = Column(Integer, primary_key= True, autoincrement= True)# id字段,主鍵,自動(dòng)增長(zhǎng) ????hostname = Column(String(64),unique= True,nullable= False)# hostname字段,唯一,不能為空 ????ip_addr = Column(String(64),unique= True,nullable= False)#ip_addr字段,唯一,不能為空 ????port = Column(Integer, default = 22) # port字段,整形,默認(rèn)22 ????def __repr__(self): ????????return "<Hostobject:id=%s, hostname=%s, ip_addr=%s, port=%s>" %(self.id, self.hostname, self.ip_addr, self.port) class Group(Base): ????__tablename__ = 'group' # 表名group ????id = Column(Integer, primary_key = True) # id字段,主鍵,自動(dòng)增長(zhǎng) ????name = Column(String(64), unique = True, nullable = False) # name字段,唯一,不為空 ????def __repr__(self): ????????return "<Groupobject: id=%s, name=%s>" %(self.id, self.name) class UserProfile(Base): ????__tablename__ = 'user_profile' # 表名user_profile ????id = Column(Integer, primary_key = True) # id字段,主鍵,自動(dòng)增長(zhǎng) ????username = Column(String(64), unique = True, nullable = False) # username字段,唯一,不為空 ????password = Column(String(255), nullable = False) # password字段,不為空 ????hostusers = relationship('HostUser', secondary = UserProfileToHostUser.__tablename__, backref = 'user_profiles') # 多對(duì)多關(guān)聯(lián)HostUser表類(lèi)(注意不是表名),中間表類(lèi)UserProfileToHostUser(注意不是表名),反向字段為user_profiles ????groups = relationship('Group', secondary = UserProfileToGroup.__tablename__, backref = 'user_profiles') # 多對(duì)多關(guān)聯(lián)Group表類(lèi)(注意不是表名),中間表類(lèi)UserProfileToGroup(注意不是表名),反向字段為user_profiles ????def __repr__(self): ????????return "<UserProfileobject: id=%s, username=%s>" %(self.id, self.username) class HostUser(Base): ????__tablename__ = 'host_user' # 表名host_user ????id = Column(Integer, primary_key = True) # id字段,主鍵,自動(dòng)增長(zhǎng) ????host_id = Column(Integer, ForeignKey('host.id')) # host_id,外鍵關(guān)聯(lián)host表的id字段 ????AuthTypes = [ ????????(u'ssh-password', u'SSH/Password'), ????????(u'ssh-key', u'SSH/Key'), ????] # 選項(xiàng)列表 ????auth_type = Column(ChoiceType(AuthTypes)) # auth_type字段,只能是選項(xiàng)列表里規(guī)定的值 ????username = Column(String(64), nullable = True) # username字段,不為空 ????password = Column(String(255)) # password字段 ????host = relationship('Host', backref = 'host_users') ????groups = relationship('Group', secondary = HostUserToGroup.__tablename__, backref = 'host_users') # 多對(duì)多關(guān)聯(lián)Group表類(lèi)(注意不是表名),中間表類(lèi)HostUserToGroup(注意不是表名),反向字段為host_users ????__table_args = (UniqueConstraint('host_id', 'username', name = '_host_username_uc')) # host_id和username組成聯(lián)合唯一約束 ????def __repr__(self): ????????return "<HostUserobject: id=%s, host_id=%s, username=%s>" %(self.id, self.host_id, self.username)

?

構(gòu)建關(guān)系表實(shí)現(xiàn)多對(duì)多實(shí)例如下:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 from sqlalchemy import create_engine,and_,or_,func,Table from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String,\ ????ForeignKey, UniqueConstraint, DateTime from sqlalchemy.orm import sessionmaker,relationship from sqlalchemy_utils import ChoiceType,PasswordType from datetime import datetime Base = declarative_base() #生成sqlorm基礎(chǔ)類(lèi) HostUserToGroup = Table('hostuser_to_group', Base.metadata,? # 表名hostuser_to_group ????Column('hostuser_id', ForeignKey('host_user.id'), primary_key = True), # 外鍵關(guān)聯(lián)host_user表的id字段 ????Column('group_id', ForeignKey('group.id'), primary_key = True), # 外鍵關(guān)聯(lián)group表的id字段 ) UserProfileToGroup = Table('userprofile_to_group', Base.metadata, # 表名userprofile_to_group ????Column('userprofile_id', ForeignKey('user_profile.id'), primary_key = True), # 外鍵關(guān)聯(lián)user_profile表的id字段 ????Column('group_id', ForeignKey('group.id'), primary_key = True), # 外鍵關(guān)聯(lián)group表的id字段 ) UserProfileToHostUser = Table('userprofile_to_hostuser', Base.metadata, # 表名userprofile_to_hostuser ????Column('userprofile_id', ForeignKey('user_profile.id'), primary_key = True), # 外鍵關(guān)聯(lián)user_profile表的id字段 ????Column('hostuser_id', ForeignKey('host_user.id'), primary_key = True), # 外鍵關(guān)聯(lián)host_user表的id字段 ) class Host(Base): ????__tablename__ = 'host' #表名host ????id = Column(Integer, primary_key= True, autoincrement= True)# id字段,主鍵,自動(dòng)增長(zhǎng) ????hostname = Column(String(64),unique= True,nullable= False)# hostname字段,唯一,不能為空 ????ip_addr = Column(String(64),unique= True,nullable= False)#ip_addr字段,唯一,不能為空 ????port = Column(Integer, default = 22) # port字段,整形,默認(rèn)22 ????def __repr__(self): ????????return "<Hostobject:id=%s, hostname=%s, ip_addr=%s, port=%s>" %(self.id, self.hostname, self.ip_addr, self.port) class Group(Base): ????__tablename__ = 'group' # 表名group ????id = Column(Integer, primary_key = True) # id字段,主鍵,自動(dòng)增長(zhǎng) ????name = Column(String(64), unique = True, nullable = False) # name字段,唯一,不為空 ????def __repr__(self): ????????return "<Groupobject: id=%s, name=%s>" %(self.id, self.name) class UserProfile(Base): ????__tablename__ = 'user_profile' # 表名user_profile ????id = Column(Integer, primary_key = True) # id字段,主鍵,自動(dòng)增長(zhǎng) ????username = Column(String(64), unique = True, nullable = False) # username字段,唯一,不為空 ????password = Column(String(255), nullable = False) # password字段,不為空 ????hostusers = relationship('HostUser', secondary = UserProfileToHostUser, backref = 'user_profiles') # 多對(duì)多關(guān)聯(lián)HostUser表類(lèi)(注意不是表名),中間表類(lèi)UserProfileToHostUser(注意不是表名),反向字段為user_profiles ????groups = relationship('Group', secondary = UserProfileToGroup, backref = 'user_profiles') # 多對(duì)多關(guān)聯(lián)Group表類(lèi)(注意不是表名),中間表類(lèi)UserProfileToGroup(注意不是表名),反向字段為user_profiles ????def __repr__(self): ????????return "<UserProfileobject: id=%s, username=%s>" %(self.id, self.username) class HostUser(Base): ????__tablename__ = 'host_user' # 表名host_user ????id = Column(Integer, primary_key = True) # id字段,主鍵,自動(dòng)增長(zhǎng) ????host_id = Column(Integer, ForeignKey('host.id')) # host_id,外鍵關(guān)聯(lián)host表的id字段 ????AuthTypes = [ ????????(u'ssh-password', u'SSH/Password'), ????????(u'ssh-key', u'SSH/Key'), ????] # 選項(xiàng)列表 ????auth_type = Column(ChoiceType(AuthTypes)) # auth_type字段,只能是選項(xiàng)列表里規(guī)定的值 ????username = Column(String(64), nullable = True) # username字段,不為空 ????password = Column(String(255)) # password字段 ????host = relationship('Host', backref = 'host_users') ????groups = relationship('Group', secondary = HostUserToGroup, backref = 'host_users') # 多對(duì)多關(guān)聯(lián)Group表類(lèi)(注意不是表名),中間表類(lèi)HostUserToGroup(注意不是表名),反向字段為host_users ????__table_args = (UniqueConstraint('host_id', 'username', name = '_host_username_uc')) # host_id和username組成聯(lián)合唯一約束 ????def __repr__(self): ????????return "<HostUserobject: id=%s, host_id=%s, username=%s>" %(self.id, self.host_id, self.username)

?

Linking Relationships with Backref?

簡(jiǎn)單來(lái)說(shuō),?relationship函數(shù)是sqlalchemy對(duì)關(guān)系之間提供的一種便利的調(diào)用方式, backref參數(shù)則對(duì)關(guān)系提供反向引用的聲明。

The backref keyword argument was first introduced in Object Relational Tutorial, and has been mentioned through- out many of the examples here. What does it actually do ? Let’s start with the canonical User and Address scenario:?

?
1 2 3 4 5 6 7 8 9 10 11 from sqlalchemy import Integer, ForeignKey, String, Column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship Base = declarative_base() class User(Base): __tablename__ = 'user' id = Column(Integer, primary_key=True) name = Column(String) ????addresses = relationship("Address", backref="user") class Address(Base): __tablename__ = 'address' id = Column(Integer, primary_key=True) email = Column(String) user_id = Column(Integer, ForeignKey('user.id'))

?

The above configuration establishes a collection of Address objects on User called User.addresses. It also establishes a .user attribute on Address which will refer to the parent User object.

In fact, the backref keyword is only a common shortcut for placing a second relationship() onto the Address mapping, including the establishment of an event listener on both sides which will mirror attribute op- erations in both directions. The above configuration is equivalent to:?

?
1 2 3 4 5 6 7 8 9 10 11 12 from sqlalchemy import Integer, ForeignKey, String, Column <br>from sqlalchemy.ext.declarative import declarative_base <br>from sqlalchemy.orm import relationship Base = declarative_base() class User(Base): ????__tablename__ = 'user' ????id = Column(Integer, primary_key=True) name = Column(String) ????addresses = relationship("Address", back_populates="user") class Address(Base): ????__tablename__ = 'address' ????id = Column(Integer, primary_key=True) ????email = Column(String) ????user_id = Column(Integer, ForeignKey('user.id')) ????user = relationship("User", back_populates="addresses")

Above, we add a .user relationship to Address explicitly. On both relationships, the back_populates directive tells each relationship about the other one, indicating that they should establish “bidirectional” behavior between each other. The primary effect of this configuration is that the relationship adds event handlers to both attributes which have the behavior of “when an append or set event occurs here, set ourselves onto the incoming attribute using this particular attribute name”. The behavior is illustrated as follows. Start with a User and an Address instance. The .addresses collection is empty, and the .user attribute is None:?

下面來(lái)看下backref相關(guān)的源碼

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def backref(name, **kwargs): ????"""Create a back reference with explicit keyword arguments, which are???? the same arguments one can send to :func:`relationship`. ????Used with the ``backref`` keyword argument to :func:`relationship` in ????place of a string argument, e.g.:: ????????'items':relationship( ????????????SomeItem, backref=backref('parent', lazy='subquery')) ????.. seealso:: ????????:ref:`relationships_backref` ????""" ????return (name, kwargs)

?

?
1 2 3 4 5 6 7 param backref: ??????????indicates the string name of a property to be placed on the related ??????????mapper's class that will handle this relationship in the other ??????????direction. The other property will be created automatically ??????????when the mappers are configured.? Can also be passed as a ??????????:func:`.backref` object to control the configuration of the ??????????new relationship.

?

轉(zhuǎn)載于:https://www.cnblogs.com/wxzbk/p/10499534.html

總結(jié)

以上是生活随笔為你收集整理的SQLAlchemy_定义(一对一/一对多/多对多)关系的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。