文章目录
一.数据定义
1.字段类型
字段类型主要有:Integer、String、Date、Boolean
2.约束
primary_key (主键)
autoincrement (主键自增长)
unique (唯一)
default (默认)
index (索引)
not null (非空)
ForeignKey (外键):主要是用来约束级联数据
db.Column( db.Integer, db.ForeignKey(xxx.id) )
使用relationship实现级联数据获取。
二.模型关系
1.一对多
(1)模型的设计
在models文件中:
class Teacher(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(32))
class Students(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(32))
#外键 ForeignKey中的值是:主表模型的小写.id
teacher_id = db.Column(db.Integer, db.ForeignKey('teacher.id'))
生成迁移文件,并升级刷新。
值得注意的是:
flask中模型迁移之后,普通字段默认可以为null
django中模型迁移之后,普通字段默认是not null
(2)添加主表数据
在views文件中:
@blue.route('/addTeacher/')
def addTeacher():
t = Teacher()
t.name = '源一'
db.session.add(t)
db.session.commit()
return '添加成功'
运行结果:
(3)添加从表数据
@blue.route('/addStudents/')
def addStudents():
s = Students()
s.name = '学一'
db.session.add(s)
db.session.commit()
return '添加成功'
运行结果:
注意:在添加从表数据时,外键默认的情况下是可以为null。 因为在flask中模型迁移的时候,所有的非主键字段,都是可以设置为null。
(4)通过关系添加主从表数据
models文件中,在class Teacher(db.Model)中添加: student_list = db.relationship(‘Students’, backref=‘teacher’, lazy=True)
class Teacher(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(32))
student_list = db.relationship('Students', backref='teacher', lazy=True)
添加后,需要重新迁移一下。
参数1 Students: 子模型的名字
参数2 backref=‘teacher’ :主模型名字的小写
参数3 lazy默认True,可以不写
relationship 在表结构中是没有字段,但是我们可以通过模型来调用。
在views文件中添加:
@blue.route('/addTeacherRelation/')
def addTeacherRelation():
teacher = Teacher()
teacher.name = '源一'
s1 = Students()
s1.name = '学一'
s2 = Students()
s2.name = '学二'
student_list = [s1, s2]
teacher.student_list = student_list
db.session.add(teacher)
db.session.commit()
return '添加成功'
运行结果:
注意:
- teacher里面有2个属性:一个是name、 一个是student_list
name可以直接赋值,是正常的字符串
student_list 是一个Students的一个列表- 有relationship后,添加主表的数据,会紧接着添加从表的数据,relationship控制着从表的数据,自动添加进去。
(5)根据主表数据查询从表数据
在没有添加relationship时的书写方式
@blue.route('/getStudents/')
def getStudents():
name = request.args.get('name')
#加[0]是为了将basequery的数据拿出来变成一个teacher对象
#teacher对象能调用该对象的属性
teacher = Teacher.query.filter(Teacher.name == name)[0]
student_list = Students.query.filter(Students.teacher_id == teacher.id)
for student in student_list:
print(student.id,student.name)
return '查询成功'
在添加了relationship之后的书写方式
@blue.route('/getStudents/')
def getStudents():
name = request.args.get('name')
students = Teacher.query.filter(Teacher.name==name)[0].student_list
for student in students:
print(student.id,student.name)
return '查询成功'
运行结果:
(6)根据从表数据查询主表数据
在没有添加backref的情况下
@blue.route('/getTeacher/')
def getTeacher():
name = request.args.get('name')
student = Students.query.filter(Students.name == name)[0]
teacher = Teacher.query.filter(Teacher.id == student.teacher_id)[0]
print(teacher.name)
return '查询成功'
在添加backref的情况下
@blue.route('/getTeacher/')
def getTeacher():
#backref是反向引用需要依赖的属性
name = request.args.get('name')
teacher = Students.query.filter(Students.name==name)[0].teacher
print(teacher.name)
return '查询成功'
运行结果:
(7)参数介绍
1.relationship函数
sqlalchemy对关系之间提供的一种便利的调用方式,关联不同的表;
2.backref参数
对关系提供反向引用的声明,在Students类上声明新属性的简单方法,之后可以在Students.teacher来获取这个地址的teacher;
3.lazy参数
(1)‘select’(默认值)
SQLAlchemy 会在使用一个标准 select 语句时一次性加载数据;
(2)‘joined’
让 SQLAlchemy 当父级使用 JOIN 语句是,在相同的查询中加载关系;
(3)‘subquery’
类似 ‘joined’ ,但是 SQLAlchemy 会使用子查询;
(4)‘dynamic’:
SQLAlchemy 会返回一个查询对象,在加载这些条目时才进行加载数据,大批量数据查询处理时推荐使用。
4.ForeignKey参数
代表一种关联字段,将两张表进行关联的方式,表示一个student的外键,设定上必须要能在父表中找到对应的id值。
2.一对一
在models中添加:
class Man(db.Model):
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
name = db.Column(db.String(32))
#一对一,useList不要使用列表
women = db.relationship('Women',backref='man',lazy=True,uselist=False)
class Women(db.Model):
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
name = db.Column(db.String(32))
man_id = db.Column(db.Integer,db.ForeignKey('man.id'))
一对一需要设置relationship中的uselist=Flase,其他数据库操作一样。
3.多对多
企业级开发中,大部分遇到的业务逻辑是一对多或者多对多
这里拿用户和电影为例
在models文件中:
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(32))
class Movie(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(32))
# 关系表
class Collection(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
# 外键,包含了User和Movie的主键
u_id = db.Column(db.Integer, db.ForeignKey(User.id))
m_id = db.Column(db.Integer, db.ForeignKey(Movie.id))
# 商品数量
num = db.Column(db.Integer, default=1)
在views文件中添加:
需求:
1.用户登陆之后买东西,第一次买会将商品添加到collection中
2.如果是第二次购买同样的商品,那么就会将该商品的num加1
@blue.route('/addCollection/')
def addCollection():
user = User.query.get(1)
movie = Movie.query.get(1)
# 看collection中这个用户用没有购买过这个电影票
# 链式调用
collections = Collection.query.filter(Collection.u_id==user.id).filter(Collection.m_id==movie.id)
if collections.count() > 0:
collection = collections.first()
collection.num = collection.num + 1
else:
collection = Collection()
collection.u_id = user.id
collection.m_id = movie.id
db.session.add(collection)
db.session.commit()
return '添加成功'
运行结果: