我們知道,<學生、課程、選課>,是一個典型的多對多關系。
 現分別用 SQLAlchemy 與 fask-SQLAlchemy 實現。
聲明:本人實測通過。
使用 SQLAlchemy
from sqlalchemy import Table, Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
# 下表是用於關系的輔助表。對於這個輔助表, 強烈建議 不 使用模型,而是采用一個實際的表
# 此說法來源於:https://segmentfault.com/q/1010000003769460
# 選課表
sc = Table('sc', Base.metadata,
    Column('sno', String(10), ForeignKey('student.sno')),
    Column('cno', String(10), ForeignKey('course.cno'))
    )
# 學生表
class Student(Base):
    __tablename__ = 'student'
    sno = Column(String(10), primary_key=True)
    sname = Column(String(10))
    
    courses = relationship('Course',
         secondary=sc,
         backref=backref('student',lazy='dynamic'),
         lazy='dynamic'
         )
    
    def __repr__(self):
        return "<Student(sno='%s', sname='%s')>" % (self.sno, self.sname)
# 課程表
class Course(Base):
    __tablename__ = 'course'
    cno = Column(String(10), primary_key=True)
    cname = Column(String(10), index=True)
    
    students = relationship('Student',
         secondary=sc,
         backref=backref('course',lazy='dynamic'),
         lazy='dynamic'
         )
    def __repr__(self):
        return "<Course(cno='%s', cname='%s')>" % (self.cno, self.cname)
    
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
DB_CONNECT_STRING = 'sqlite://' # 'sqlite:///:memory:'
engine = create_engine(DB_CONNECT_STRING, echo=False)
DB_Session = sessionmaker(bind=engine)
session = DB_Session()
# 1. 創建表(如果表已經存在,則不會創建)
Base.metadata.create_all(engine)
# 2. 插入數據
# 不能這樣:Student('201701', '張三')
some_students = [Student(sno='201701', sname='張三'),
                 Student(sno='201702', sname='李四'),
                 Student(sno='201703', sname='王五'),
                 Student(sno='201704', sname='趙六')]
session.add_all(some_students)
some_courses = [Course(cno='#1', cname='C'),
                Course(cno='#2', cname='C++'),
                Course(cno='#3', cname='Java'),
                Course(cno='#4', cname='Python')]
session.add_all(some_courses)
session.execute(sc.insert().values(sno='201701', cno='#1'))
session.execute(sc.insert().values(sno='201701', cno='#4'))
session.execute(sc.insert().values(sno='201702', cno='#2'))
session.execute(sc.insert().values(sno='201703', cno='#3'))
session.execute(sc.insert().values(sno='201704', cno='#4'))
session.commit()
#查詢
student = session.query(Student).filter_by(sname='張三').one()
courses  = student.course.all()  #該學生選擇的所有課程
print(courses)
course = session.query(Course).filter_by(cname='Python').one()
students  = course.student.all()  #選擇該課程的所有學生
print(students)
 
         
         
        使用 flask-SQLAlchemy
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
# 學生-課程表(用於關系的輔助表。對於這個輔助表, 強烈建議 不 使用模型,而是采用一個實際的表)
sc = db.Table('sc',
    db.Column('sno', db.String(10), db.ForeignKey('student.sno')),
    db.Column('cno', db.String(10), db.ForeignKey('course.cno'))
    )
# 學生表
class Student(db.Model):
    __tablename__ = 'student'
    
    sno = db.Column(db.String(10), primary_key=True)
    sname = db.Column(db.String(10))
    
    courses = db.relationship('Course',
         secondary=sc,
         backref=db.backref('student',lazy='dynamic'),
         lazy='dynamic'
         )
    
    def __init__(self, sno, sname):
        self.sno = sno
        self.sname = sname
        
    def __repr__(self):
        return "<Student(sno='%s', sname='%s')>" % (self.sno, self.sname)
    
# 課程表
class Course(db.Model):
    __tablename__ = 'course'
    
    cno = db.Column(db.String(10), primary_key=True)
    cname = db.Column(db.String(10), index=True)
    
    students = db.relationship('Student',
         secondary=sc,
         backref=db.backref('course',lazy='dynamic'),
         lazy='dynamic'
         )
    
    def __init__(self, cno, cname):
        self.cno = cno
        self.cname = cname
        
    def __repr__(self):
        return "<Course(cno='%s', cname='%s')>" % (self.cno, self.cname)
        
# 1. 創建表(如果表已經存在,則不會創建)
db.create_all()
# 2. 插入數據
some_students = [Student('201701', '張三'),
                 Student('201702', '李四'),
                 Student('201703', '王五'),
                 Student('201704', '趙六')]
db.session.add_all(some_students)
some_courses = [Course('#1', 'C'),
                Course('#2', 'C++'),
                Course('#3', 'Java'),
                Course('#4', 'Python')]
db.session.add_all(some_courses)
#scs = [sc(201701, 1), # 報錯:"Table" object is not callable
#       sc(201701, 4),
#       sc(201702, 2),
#       sc(201703, 3),
#       sc(201704, 4)]
#db.session.add_all(scs)
# 改正如下
db.session.execute(sc.insert().values(sno='201701', cno='#1'))
db.session.execute(sc.insert().values(sno='201701', cno='#4'))
db.session.execute(sc.insert().values(sno='201702', cno='#2'))
db.session.execute(sc.insert().values(sno='201703', cno='#3'))
db.session.execute(sc.insert().values(sno='201704', cno='#4'))
db.session.commit()
#查詢
student = Student.query.filter_by(sname='張三').one()
courses  = student.course.all()  #該學生選擇的所有課程
print(courses)
course = Course.query.filter_by(cname='Python').one()
students  = course.student.all()  #選擇該課程的所有學生
print(students)
 
         
         
         
       