SQLAlchemy的ORM(4)
如果想深入學(xué)習(xí)Flask量承,可以觀看這套免費(fèi)Flask教學(xué)視頻:零基礎(chǔ):Flask入門到項(xiàng)目實(shí)戰(zhàn)
表關(guān)系:
表之間的關(guān)系存在三種:一對(duì)一曙强、一對(duì)多、多對(duì)多算谈。而SQLAlchemy
中的ORM
也可以模擬這三種關(guān)系粉楚。因?yàn)橐粚?duì)一其實(shí)在SQLAlchemy
中底層是通過一對(duì)多的方式模擬的,所以先來看下一對(duì)多的關(guān)系:
外鍵:
在Mysql中潘酗,外鍵可以讓表之間的關(guān)系更加緊密。而SQLAlchemy同樣也支持外鍵雁仲。通過ForeignKey類來實(shí)現(xiàn)仔夺,并且可以指定表的外鍵約束。相關(guān)示例代碼如下:
class Article(Base):
__tablename__ = 'article'
id = Column(Integer,primary_key=True,autoincrement=True)
title = Column(String(50),nullable=False)
content = Column(Text,nullable=False)
uid = Column(Integer,ForeignKey('user.id'))
def __repr__(self):
return "<Article(title:%s)>" % self.title
class User(Base):
__tablename__ = 'user'
id = Column(Integer,primary_key=True,autoincrement=True)
username = Column(String(50),nullable=False)
外鍵約束有以下幾項(xiàng):
-
RESTRICT
:父表數(shù)據(jù)被刪除攒砖,會(huì)阻止刪除缸兔。默認(rèn)就是這一項(xiàng)。 -
NO ACTION
:在MySQL中吹艇,同RESTRICT
惰蜜。 -
CASCADE
:級(jí)聯(lián)刪除。 -
SET NULL
:父表數(shù)據(jù)被刪除受神,子表數(shù)據(jù)會(huì)設(shè)置為NULL抛猖。
一對(duì)多:
拿之前的User
表為例,假如現(xiàn)在要添加一個(gè)功能鼻听,要保存用戶的郵箱帳號(hào)财著,并且郵箱帳號(hào)可以有多個(gè),這時(shí)候就必須創(chuàng)建一個(gè)新的表撑碴,用來存儲(chǔ)用戶的郵箱撑教,然后通過user.id
來作為外鍵進(jìn)行引用,先來看下郵箱表的實(shí)現(xiàn):
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
class Address(Base):
__tablename__ = 'address'
id = Column(Integer,primary_key=True)
email_address = Column(String,nullable=False)
# User表的外鍵醉拓,指定外鍵的時(shí)候伟姐,是使用的是數(shù)據(jù)庫表的名稱,而不是類名
user_id = Column(Integer,ForeignKey('users.id'))
# 在ORM層面綁定兩者之間的關(guān)系廉嚼,第一個(gè)參數(shù)是綁定的表的類名玫镐,
# 第二個(gè)參數(shù)back_populates是通過User反向訪問時(shí)的字段名稱
user = relationship('User',back_populates="addresses")
def __repr__(self):
return "<Address(email_address='%s')>" % self.email_address
# 重新修改User表,添加了addresses字段怠噪,引用了Address表的主鍵
class User(Base):
__tablename__ = 'users'
id = Column(Integer,primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(100))
# 在ORM層面綁定和`Address`表的關(guān)系
addresses = relationship("Address",order_by=Address.id,back_populates="user")
其中恐似,在User
表中添加的addresses
字段,可以通過User.addresses
來訪問和這個(gè)user相關(guān)的所有address傍念。在Address
表中的user
字段矫夷,可以通過Address.user
來訪問這個(gè)user。達(dá)到了雙向綁定憋槐。表關(guān)系已經(jīng)建立好以后双藕,接下來就應(yīng)該對(duì)其進(jìn)行操作,先看以下代碼:
jack = User(name='jack',fullname='Jack Bean',password='gjffdd')
jack.addresses = [Address(email_address='jack@google.com'),
Address(email_address='j25@yahoo.com')]
session.add(jack)
session.commit()
首先阳仔,創(chuàng)建一個(gè)用戶忧陪,然后對(duì)這個(gè)jack
用戶添加兩個(gè)郵箱,最后再提交到數(shù)據(jù)庫當(dāng)中,可以看到這里操作Address
并沒有直接進(jìn)行保存嘶摊,而是先添加到用戶里面延蟹,再保存。
一對(duì)一:
一對(duì)一其實(shí)就是一對(duì)多的特殊情況叶堆,從以上的一對(duì)多例子中不難發(fā)現(xiàn)阱飘,一對(duì)應(yīng)的是User
表,而多對(duì)應(yīng)的是Address
虱颗,也就是說一個(gè)User
對(duì)象有多個(gè)Address
沥匈。因此要將一對(duì)多轉(zhuǎn)換成一對(duì)一,只要設(shè)置一個(gè)User
對(duì)象對(duì)應(yīng)一個(gè)Address
對(duì)象即可忘渔,看以下示例:
class User(Base):
__tablename__ = 'users'
id = Column(Integer,primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(100))
# 設(shè)置uselist關(guān)鍵字參數(shù)為False
addresses = relationship("Address",back_populates='addresses',uselist=False)
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer,primary_key=True)
email_address = Column(String(50))
user_id = Column(Integer,ForeignKey('users.id')
user = relationship('Address',back_populates='user')
從以上例子可以看到高帖,只要在User
表中的addresses
字段上添加uselist=False
就可以達(dá)到一對(duì)一的效果。設(shè)置了一對(duì)一的效果后辨萍,就不能添加多個(gè)郵箱到user.addresses
字段了棋恼,只能添加一個(gè):
user.addresses = Address(email_address='ed@google.com')
多對(duì)多:
多對(duì)多需要一個(gè)中間表來作為連接,同理在sqlalchemy
中的orm
也需要一個(gè)中間表锈玉。假如現(xiàn)在有一個(gè)Teacher
和一個(gè)Classes
表爪飘,即老師和班級(jí),一個(gè)老師可以教多個(gè)班級(jí)拉背,一個(gè)班級(jí)有多個(gè)老師师崎,是一種典型的多對(duì)多的關(guān)系,那么通過sqlalchemy
的ORM
的實(shí)現(xiàn)方式如下:
association_table = Table('teacher_classes',Base.metadata,
Column('teacher_id',Integer,ForeignKey('teacher.id')),
Column('classes_id',Integer,ForeignKey('classes.id'))
)
class Teacher(Base):
__tablename__ = 'teacher'
id = Column(Integer,primary_key=True)
tno = Column(String(10))
name = Column(String(50))
age = Column(Integer)
classes = relationship('Classes',secondary=association_table,back_populates='teachers')
class Classes(Base):
__tablename__ = 'classes'
id = Column(Integer,primary_key=True)
cno = Column(String(10))
name = Column(String(50))
teachers = relationship('Teacher',secondary=association_table,back_populates='classes')
要?jiǎng)?chuàng)建一個(gè)多對(duì)多的關(guān)系表椅棺,首先需要一個(gè)中間表犁罩,通過Table
來創(chuàng)建一個(gè)中間表。上例中第一個(gè)參數(shù)teacher_classes
代表的是中間表的表名两疚,第二個(gè)參數(shù)是Base
的元類床估,第三個(gè)和第四個(gè)參數(shù)就是要連接的兩個(gè)表,其中Column
第一個(gè)參數(shù)是表示的是連接表的外鍵名诱渤,第二個(gè)參數(shù)表示這個(gè)外鍵的類型丐巫,第三個(gè)參數(shù)表示要外鍵的表名和字段。
創(chuàng)建完中間表以后勺美,還需要在兩個(gè)表中進(jìn)行綁定递胧,比如在Teacher
中有一個(gè)classes
屬性,來綁定Classes
表赡茸,并且通過secondary
參數(shù)來連接中間表缎脾。同理,Classes
表連接Teacher
表也是如此占卧。定義完類后遗菠,之后就是添加數(shù)據(jù)联喘,請(qǐng)看以下示例:
teacher1 = Teacher(tno='t1111',name='xiaotuo',age=10)
teacher2 = Teacher(tno='t2222',name='datuo',age=10)
classes1 = Classes(cno='c1111',name='english')
classes2 = Classes(cno='c2222',name='math')
teacher1.classes = [classes1,classes2]
teacher2.classes = [classes1,classes2]
classes1.teachers = [teacher1,teacher2]
classes2.teachers = [teacher1,teacher2]
session.add(teacher1)
session.add(teacher2)
session.add(classes1)
session.add(classes2)
如果想深入學(xué)習(xí)Flask,可以觀看這套免費(fèi)Flask教學(xué)視頻:零基礎(chǔ):Flask入門到項(xiàng)目實(shí)戰(zhàn)
</article>
版權(quán)聲明: https://blog.csdn.net/huangyong1314/article/details/80555065