Flask之models(三):数据定义、模型关系

一.数据定义

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 '添加成功'

运行结果:
在这里插入图片描述

注意:

  1. teacher里面有2个属性:一个是name、 一个是student_list
       name可以直接赋值,是正常的字符串
       student_list 是一个Students的一个列表
  2. 有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 '添加成功'

运行结果:
在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值