亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Flask sqlalchemy一對多與多對一與一對一及多對多關系介紹

 更新時間:2022年09月06日 16:11:01   作者:weixin_42576837  
這篇文章主要介紹了Flask sqlalchemy一對多與多對一與一對一及多對多關系介紹,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

這里以作者和文章來演示一對多的關系:一個作者可以有多篇文章,但是一篇文章只能有一個作者。

配置項

首先,配置下數(shù)據(jù)庫config.py

username = 'xxxx'
password = 'xxxx'
database = 'school'
hostname = 'localhost'
port = '3306'
uri = f'mysql+pymysql://{username}:{password}@{hostname}:{port}/{database}'
SQLALCHEMY_DATABASE_URI  = uri
SQLALCHEMY_TRACK_MODIFICATIONS = False

在app.py文件中導入配置

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config
app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app)

接著創(chuàng)建模型類,建立python類到數(shù)據(jù)表的映射:

定義外鍵

class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    name = db.Column(db.String(100),nullable=False)
class Article(db.Model):
    __tablename__ = 'article'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    title = db.Column(db.String(200),nullable=False)
    content = db.Column(db.Text,nullable=False)
    user_id = db.Column(db.Integer,db.ForeignKey('user.id')) 

由于一個作者可以有多篇文章,所以外鍵應該設置在Article類中,這樣每一篇文章的user_id字段都只會有一個值,因為只對應一個作者。

假設,在User類中存在外鍵字段article_id,那么一個作者的所有文章都需要存放在這一個字段中,但是外鍵只能存放單一數(shù)據(jù)(表量),所以外鍵的設置總是在“多”的這一側(cè)定義。

定義關系屬性

為什么需要關系屬性,具體的原因我也不清楚,我想可能是從查詢的角度來說,會更方便。

定義關系屬性需要使用關系函數(shù)。關系屬性在關系的出發(fā)側(cè)定義,即一對多關系的“一”這一側(cè)。一個作者擁有多篇文章,我們在User模型類中,定義一個叫articles的關系屬性,用它可以表示每一個作者所對應的多篇文章。

class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    name = db.Column(db.String(100),nullable=False)
    articles = db.relationship('Article',backref=db.backref('user'))

articles 字段使用db.relationship()關系函數(shù)定義為關系屬性,這個關系屬性將返回多個記錄。

  • relationship()函數(shù)的第一個參數(shù)為關系另一側(cè)的模型名稱,是python類的名稱,不是數(shù)據(jù)表名稱。
  • 第二個參數(shù)表示添加反向引用,會自動在另一側(cè),也就是Article模型中,建立一個關系屬性,這個字段叫user,使用這個字段可以查找到文章所對應的用戶。

現(xiàn)在user表中多了一個字段articles,但是它并不是數(shù)據(jù)庫層面的,實際的表中并沒有這個字段,可以認為只是一個查詢接口。

接著創(chuàng)建數(shù)據(jù)表并插入數(shù)據(jù):

 u1 = User(name='zs')
 a1 = Article(title='西游記',content='西游記是四大名著')
 a1.author = u1
 db.session.add(a1)
 db.session.commit()

創(chuàng)建了一個user表的記錄,一個article表的記錄,如何讓他們建立聯(lián)系呢?使用關系屬性字段:

文章唯一指向一個作者:

a1.author = u1

直接將作者的實例對象u1賦值給文章實例對象a1的author字段,他們就會建立關系,文章表中的user_id字段就會指向那個作者。

article表

user表

現(xiàn)在用戶zs擁有兩篇文章,嘗試使用關系屬性查詢。

u1 = User.query.filter_by(name='zs').first()
print(u1.articles)

輸出user表的articles字段:

[<Article 1>, <Article 2>]

可以發(fā)現(xiàn)這個字段里面是兩條記錄,是article表中的兩條記錄,因為這兩篇文章都是zs的文章,所以通過這個關系屬性字段,可以獲取到一個作者對應的所有文章。

反過來,關于反向引用,backref=db.backref('user'),它會在Article也建立一個關系屬性,這個字段叫做user,可以通過這個字段獲取到文章對應的作者。

比如:

#先找到文章
article1 = Article.query.filter_by(title='西游記').first()
#使用反向引用的字段,user,獲取到這個文章對應的作者
print(article1.user)

輸出:

<User 1>

雙向的關系屬性

上面在建立關系屬性是,只是在User類中使用了關系屬性:

articles = db.relationship('Article',backref=db.backref('user'))

這種方式,會隱式的在Article類中也建立一個關系屬性user。我們可以使用back_populates參數(shù)顯式的建立雙向的關系屬性。

這里仍然以作者author和文章article為例,一個作者可以有多篇文章,一篇文章只能有一個作者,建立顯示的雙向關系屬性。

class User(db.Model):
    __tablename__ = 'author'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    name = db.Column(db.String(100),nullable=False)
    #關系屬性
    articles = db.relationship('Article',back_populates='authors')
class Article(db.Model):
    __tablename__ = 'article'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    title = db.Column(db.String(200),nullable=False)
    content = db.Column(db.Text,nullable=False)
    auth_id = db.Column(db.Integer, db.ForeignKey('author.id'))
    #關系屬性
    authors = db.relationship('User',back_populates='articles')

在一的一側(cè),User類中,建立了關系屬性,articles,獲取一個作者對應的多個文章記錄。

在多的一側(cè),Article類中,建立了關系屬性,authors,獲取每一篇文章對應的一個作者記錄。

使用back_populates參數(shù)連接對方,參數(shù)值需要設置為關系另一側(cè)的關系屬性名。

使用關系屬性添加數(shù)據(jù)

u1 = User(name='zs')
a1 = Article(title='西游記', content='西游記是四大名著')
a2 = Article(title='紅樓夢', content='紅樓夢是四大名著')
a1.authors = u1
a2.authors = u1
db.session.add_all([a1,a2])
db.session.commit()

實例化User類對象u1,Article類對象a1,a2。

然后使用Article類的關系屬性字段,authors

將User類對象u1賦值給Article類對象的關系屬性authors

或者反過來,使用用戶的關系屬性字段articles添加數(shù)據(jù):

def insert():
    u1 = User(name='zs')
    a1 = Article(title='西游記',content='西游記是四大名著')
    a2 = Article(title='水滸傳',content='水滸傳是四大名著')
    u1.articles = [a1,a2]
    db.session.add(u1)
    db.session.commit()

這里的添加方式是:u1.articles = [a1,a2]

接著查詢,使用關系屬性字段就可以查詢到了,這里只是演示了使用back_populates參數(shù)顯示的建立雙向的關系屬性,之前使用的backref可以簡化關系的定義,是一種隱式的雙向關系的建立。

一對一

這里使用國家和首都演示一對一關系:每一個國家只有一個首都;反過來說,一個城市也只能作為一個國家的首都。

一對一關系實際上是通過建立雙向關系的一對多關系的基礎上轉(zhuǎn)化而來的。

class Country(db.Model):
    __tablename__ = 'country'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    name = db.Column(db.String(30),unique=True)
	capital = db.relationship('Capital',back_populates='country')
class Capital(db.Model):
    __tablename__ = 'capital'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(30),unique=True)
    #外鍵在哪一個表中設置應該都可以
    country_id = db.Column(db.Integer,db.ForeignKey('country.id'))
    #設置關系屬性
    country = db.relationship('Country',back_populates='capital')

首先上面是一個雙向的關系屬性,這時候表的關系和之前的一對多沒有區(qū)別,現(xiàn)在我們需要給關系屬性中假如一個參數(shù)uselist=False

”一“的一側(cè)加入,就是在Country類模型中加入

capital = db.relationship('Capital',back_populates='country',uselist=False)

加入這個參數(shù)以后,在使用Country.capital獲取記錄時,將限制只返回一條記錄。

由于Capital中設置了外鍵country_id ,存儲單一數(shù)據(jù),一個記錄的country_id 只會對應Country中的一個記錄。

這是一對多關系就變成了一對一關系。

測試一對一:

首先插入數(shù)據(jù),插入一個國家記錄,一個城市記錄,然后建立關系。

def insert():
    china = Country(name='中國')
    Beijing = Capital(name='北京')
    Beijing.country = china
    db.session.add(Beijing)
    db.session.commit()

這樣,Country表中就有了

capital表中:

他們目前時一對一的關系,那么,假如現(xiàn)在新增一個城市,它的country_id指向中國,

這時候就變成了一個國家,對應兩個城市,變成了一對多,但是我們定義的是一對一,這樣可行嗎?

def f():
    #首先拿到中國的這條記錄
    china = Country.query.filter_by(name='中國')
    china = china.first()
    print(china)
    #新增城市,
    Guangzhou = Capital(name='廣州')
    #建立廣州與中國之間的關系
    Guangzhou.country = china
    db.session.add(Guangzhou)
    db.session.commit()
    print('success')

執(zhí)行這個函數(shù)之后,數(shù)據(jù)表會有以下變化:

可以看到capital表中的北京這條記錄的country_id值變成了NULL,這正是因為我們建立的關系時一對一的,不允許變成一對多,所以,會把之前的對應關系取消掉。假如刪除了參數(shù)uselist=False,就可以建立一對多的關系了。

多對多

這里使用學生和老師來演示多對多關系:每個學生有多個老師,每個老師也可以有多個學生。

在一對多關系中,我們可以在”多“這一側(cè)添加外鍵指向”一“這一側(cè),外鍵只能存儲一個記錄,但是在多對多關系中,每一個記錄都可以與關系另一側(cè)的多個記錄建立關系,關系兩側(cè)的模型都需要存儲一組外鍵。

在SQLAlchemy中,要想表示多對多關系,除了關系兩側(cè)的模型外,我們還需要創(chuàng)建一個關聯(lián)表(association table)。關聯(lián)表不存儲數(shù)據(jù),只用來存儲關系兩側(cè)模型的外鍵對應關系,

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config
app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app)
#關聯(lián)表
association_table = db.Table('stu_tea_associ',#關聯(lián)表的名稱
    db.Column('student_id',db.Integer,db.ForeignKey('student.id')),#字段student_id,類型,關聯(lián)的外鍵
    db.Column('teacher_id',db.Integer,db.ForeignKey('teacher.id')))#字段teacher_id,類型,關聯(lián)的外鍵
#學生表
class Student(db.Model):
    __tablename__ = 'student'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    name = db.Column(db.String(20))
    #建立關系屬性
    teachers = db.relationship('Teacher',secondary=association_table,back_populates='students')
#教師表
class Teacher(db.Model):
    __tablename__ = 'teacher'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    name = db.Column(db.String(20))
    #建立關系屬性
    students = db.relationship('Student', secondary=association_table, back_populates='teachers')

關聯(lián)表使用db.Table類定義,傳入的第一個參數(shù)是關聯(lián)表的名稱。我們在關聯(lián)表中定義了兩個字段student_id,teacher_id,這兩個字段作為外鍵,與student.id,teacher.id兩個字段關聯(lián)起來。

另外,這里建立的關系屬性是雙向的關系屬性,參數(shù)secondary='關聯(lián)表名稱'。

接著,利用關系屬性添加數(shù)據(jù)

def insert():
    stu1 = Student(name='小明')
    stu2 = Student(name='小紅')
    tea1 = Teacher(name='張三')
    tea2 = Teacher(name='李四')
    #學生1的老師有多個
    #由于是多對多關系,所以會采用列表的形式進行外鍵的orm賦值
    stu1.teachers = [tea1,tea2]
    #學生2的老師有多個
    stu2.teachers = [tea1,tea2]
    db.session.add(stu1)
    db.session.add(stu2)
    db.session.commit()

調(diào)用關系屬性賦值的時候,這里需要使用列表的形式添加。

student:

teacher:

關聯(lián)表:association_table:

接著,使用關系屬性查詢數(shù)據(jù);

def query():
    #先查詢到小明這個同學
    stu1 = Student.query.filter_by(name='小明').first()
    #使用關系屬性輸出對應的老師
    print(stu1.teachers)
    #反過來,查找到老師,使用關系屬性輸出老師對應的所有學生
    tea1 = Teacher.query.filter_by(name='張三').first()
    print(tea1.students)

輸出記錄

[<Teacher 1>, <Teacher 2>]

[<Student 1>, <Student 2>]

到此這篇關于Flask sqlalchemy一對多與多對一與一對一及多對多關系介紹的文章就介紹到這了,更多相關Flask sqlalchemy內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論