大多數的其他關系型別都可以從一對多型別中衍生,多對一關系從“多”的一次看,就是一對多關系,一對一關系是簡化版的一對多關系,唯一不能從一對多關系中演化出來的型別就是多對多關系,
-
多對多關系
一對多,多對一,一對一關系至少都有一側是單個物體,表之間的聯系通過外鍵實作,讓外鍵指向那個物體,解決多對多的關系,需要引入第三張表,稱為關聯表,由此可以分解成原表和關聯表之間的兩個一對多關系, 比如學生選課,一個學生可以選擇多門課程,一門課程可以被多個學生選擇,這是一個典型的多對多的關系,

多對多關系在查詢時的流程:比如查找一個學生選了哪些課程,首先從學生和注冊之間的一對多關系開始,獲取學生student_id對應的所有class_id,然后在按照多對一的方向遍歷課程和注冊之間的一對多的關系,找到該學生選擇的所有課程,
1. 兩個物體多對多關系
Flask-SQLAlchemy實作多對多關系
1 registrations = db.Table('registrations', 2 db.Column('student_id', db.Integer, db.ForeignKey('students.id')), 3 db.Column('class_id', db.Integer, db.ForeignKey('classes.id'))) 4 5 class Student(db.Model): 6 __tablename__ = 'students' 7 id = db.Column(db.Integer, primary_key=True) 8 name = db.Column(db.String) 9 classes = db.relationship('Class', secondary=registrations, 10 backref = db.backref('students', lazy='dynamic'), 11 lazy='dynamic') 12 13 class Class(db.Model): 14 __tablename__ = 'classes' 15 id = db.Column(db.Integer, primary_key=True) 16 name = db.Column(db.String)
在多對多關系中,依然使用db.relationship()方法定義,但在多對多關系中,必須把secondary引數設為關聯表,多對多關系可以在任何類中定義,backref引數會處理好關系的另一側,關聯表就是一個簡單的表,不是模型,Flask-SQLAlchemy會自動接管這個表,
學生注冊課程:
1 stu.classes.append(c) 2 db.session.add(stu)
列出學生注冊的所有課程:
1 stu.classes.all()
注冊了課程c的所有學生:
1 c.students.all()
-
自參考關系
在用戶關注功能中,多對多關系中并不存在兩個物體,只有User一個物體模型,如果關系中的兩側都在同一個表中,這種關系稱為自參考關系

關聯表follows,其中每一行表示一個用戶關注另一個用戶,左側表示follower,可理解為粉絲,右側表示followed,可理解為關注別人,
使用多對多關系時,需要存盤兩個物體之間的額外資訊,比如某個用戶關注另一個用戶的時間資訊,為了能處理自定義的資料,可以將關聯表設計成可訪問的模型,
1 class Follow(db.Model): 2 __tablename__ = 'follows' 3 follower_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True) 4 followed_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True) 5 timestamp = db.Column(db.DateTime, default=datetime.utcnow) 6 7 class User(UserMixin, db.Model): 8 __tablename__ = 'users' 9 ... 10 followers = db.relationship('Follow', 11 foreign_keys=[Follow.followed_id], 12 backref=db.backref('followed', lazy='joined'), 13 lazy='dynamic', 14 cascade='all, delete-orphan') 15 followed = db.relationship('Follow', 16 foreign_keys=[Follow.follower_id], 17 backref=db.backref('follower', lazy='joined'), 18 lazy='dynamic', 19 cascade='all, delete-orphan')
引數介紹:
1. foreign_keys引數表示關聯的外鍵
2. backref引數表示將followed/follower回引Follow模型, 可以通過Follow.follower訪問粉絲,通過Follow.followed訪問關注的人
3. 回引中的lazy引數指定為joined可以實作立即從聯結查詢中加載相關物件
4. cascade引數配置在父物件上執行的操作對相關物件的影響
-
關注關系的輔助方法
1 class User(UserMixin, db.Model): 2 __tablename__ = 'users' 3 ... 4 5 # 關注某個用戶 6 def follow(self, user): 7 # 判斷是否已經關注了 8 if not self.is_following(user): 9 # 新建關聯表物件實體,記錄粉絲和被關注者的關系 10 f = Follow(follower=self, followed=user) 11 db.session.add(f) 12 13 # 取消關注某個用戶 14 def unfollow(self, user): 15 # 檢查取消的關注的用戶是否已經被關注了 16 f = self.followed.filter_by(followed_id=user.id).first() 17 if f: 18 db.session.delete(f) 19 20 # 判斷是否已經關注 21 def is_following(self, user): 22 # 確認用戶有沒有id,以防創建了用戶,但是未提交到資料庫 23 if user.id is None: 24 return False 25 return self.followed.filter_by(followed_id=user.id).first() is not None 26 27 # 判斷是否被關注 28 def is_followed_by(self, user): 29 if user.id is None: 30 return False 31 return self.followers.filter_by(follower_id=user.id).first() is not None
-
END
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/141662.html
標籤:Python
上一篇:Flask中博客類的Post實作
下一篇:Python Re模塊
