1.表关系
在MySQL中我们讲了表关系,有一对多,一对一和多对多这几种情况。同样的,我们也可以用SQLAlchemy来表示这种关系。
首先是一对多的情况:
#先查看下表结构,然后去写对应的类
mysql> SHOW CREATE TABLE `department`;
mysql> SHOW CREATE TABLE `student`;
from user import session,Base,User
from datetime import datetime,date
from sqlalchemy.orm import relationship
from sqlalchemy import Column,Integer,String,ForeignKey
class Department(Base):
__tablename__ = 'department'
id = Column(Integer,primary_key=True,autoincrement=True)
name = Column(String(10),nullable=False)
code = Column(Integer,nullable=False)
def __repr__(self):
return 'Department(id=%s,name=%s,code=%s)'%(self.id,self.name,self.code)
class Student(Base):
__tablename__='student'
id = Column(Integer,primary_key=True,autoincrement=True)
name = Column(String(10),nullable=False)
dep_id = Column(Integer,ForeignKey('department.id'),doc='学院id')
stu_dep_for_key = relationship('Department',backref='students')
def __repr__(self):
return 'Student(id=%s,name=%s,dep_id=%s)'%(self.id,self.name,self.dep_id)
if __name__=='__main__':
print(dir(Department))
rows = session.query(Department).filter(Department.id=='1').first()
print(rows.students)
print(rows)
rows = session.query(Student).filter(Student.dep_id=='1').all()
print(rows)
在上面这里,我们通过print(dir(Department))的打印值可以看到,Department的属性中增加了一个students属性,通过print(rows.students),可以看到所有Department.id=='1’的学生,这个和第二个查询的结果是一样的,在这里,我们可以很自由的决定数据是否展现出来。
讲relationship之前,先回顾一下,外键它是一个约束,但是并不是代表了关系,之前所讲的一对多,一对一和多对多关系都是在我们的逻辑上,外键约束不能代表这种关系,注意分清外键是约束,没有代表关系。
而在SQLAlchemy里面,这个relationship代表了一对多的关系,当然我们可以通过参数改变关系,它默认是一对多的关系,而这个关系是SQLAlchemy里面的,和数据库没有关系,但是relationship是和外键一起使用的。
接下来我们看看一对一的关系:
from user import session,Base,User
from datetime import datetime,date
from sqlalchemy.orm import relationship
from sqlalchemy import Column,Integer,String,ForeignKey
from department import Student
class Student_details(Base):
__tablename__='student_details'
id = Column(Integer,primary_key=True,autoincrement=True)
id_card = Column(Integer,nullable=False,unique=True)
telephone = Column(Integer)
stu_id = Column(Integer,ForeignKey('student.id'))
stu_deta_for_key = relationship('Student',backref='details',uselist=False,cascade='all')
def __repr__(self):
return 'Student_details(id=%s,id_card=%s,telephone=%s,stu_id=%s)'%(self.id,self.id_card,self.telephone,self.stu_id)
if __name__=='__main__':
rows = session.query(Student).filter(Student.id==1).first()
print(rows)
print(dir(Student))
print(rows.details)
在这里,我们实现了一对一的关系,使用的是uselist=False这个参数。cascade 是自动关系处理,就和MySQL中的ON DELETE类似,但是有区别,参数选项如下:
cascade 所有的可选字符串项是:
- all , 所有操作都会自动处理到关联对象上.
- save-update , 关联对象自动添加到会话.
- delete , 关联对象自动从会话中删除.
- delete-orphan , 属性中去掉关联对象, 则会话中会自动删除关联对象.
- merge , session.merge() 时会处理关联对象.
- refresh-expire , session.expire() 时会处理关联对象.
- expunge , session.expunge() 时会处理关联对象.
最后看下多对多的关系:
#在Studen上面添加这张表
stu_course = Table('stu_course',Base.metadata,
Column('stu_id',Integer,ForeignKey('student.id'),primary_key=True), Column('course_id',Integer,ForeignKey('course.id'),primary_key=True)
)
#在Sudent中添加这个关系
cou_select = relationship('Course',backref='students',secondary=stu_course)
#添加课程表的模块
class Course(Base):
__tablename__='course'
id = Column(Integer,primary_key=True,autoincrement=True)
name = Column(String(20),nullable=False)
stu_select = relationship('Student',backref='course',secondary=stu_course)
def __repr__(self):
return 'Course(id=%s,name=%s)'%(self.id,self.name)
if __name__=='__main__':
rows = session.query(Student).filter(Student.id==1).first()
print(rows)
print(dir(Student))
在多对多的关系中,我需要再建立一张表,使用secondary参数来表示多对多关系。
总结
使用SQLAlchemy同样也能表示表的关系,只是表达的方式有些不一样而已。