Flask中数据库的应用

一、配置SQLAlchemy

1.安装包

pip install flask-sqlalchemy
pip install pymysql

2.配置数据库

a)配置SQLALCHEMY_DATABASE_URI SQLALCHEMY_TRACK_MODIFICATIONS

>>>root 用户名
>>>password 密码
>>>localhost 数据库地址:本地数据库 / 服务器地址

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:passowrd@localhost:3306/数据库名称'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
b)初始化
SQLAlchemy(app=app)

二、model模型

1.数据类型

a)String(长度) 字符串
b)Integer 整数
c)Date 时间

2.参数

a)primary_key 主键
b)autoincrement 从1开始,每次自动增加1
c)unique 唯一
d)default 默认
e)nullable 是否允许为空值

3.创建模型

a)知识点:

>>>db = SQLAlchemy() 实例化
>>>db.Model 继承model类
>>>db.Column() 插入属性
>>>db.String(20) 数据类型
>>>__tablename__ 指定表名称
>>>def __init__(self, 参数1, 参数2) 模型初始化
初始化的作用:在创建实例时非常方便,如创建一个姓名为王小,年龄20的学生,可以直接写作:Student('王小', 20)

b)实例

创建一个学生模型,保存学生姓名、年龄信息。

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Student(db.Model):

    s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    s_name = db.Column(db.String(20), unique=True)
    s_age = db.Column(db.Integer, default=18)

    __tablename__ = 'student'


    def __init__(self, name, age):
        self.s_name = name
        self.s_age = age

创建一个班级模型,保存班级名称、班级描述、班级创建时间信息。

class Grade(db.Model):

    g_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    g_name = db.Column(db.String(10), unique=True)
    g_desc = db.Column(db.String(100),nullable=True)
    g_time = db.Column(db.Date, default=datetime.now)

    __tablename__ = 'grade'

    def __init__(self, name, desc):
        self.g_name = name
        self.s_desc = desc

>>>注意:Flask中创建的模型,不会自动创建id字段,需要自己定义。

4.一对多关系

通过如下实例阐述flask中一对多关系。
实例:给上述的学生表添加一个s_grade外键,链接到班级表,指定每个学生所在的班级。

a)学生表中添加s_grade字段:

>>>必须先指定s_grade的数据类型db.Integer,再指定外键信息db.ForeignKey。
>>>db.ForeignKey(‘参数’)
参数grade.g_id含义:grade是被关联表中__tablename__ 指定的表名称,g_id是被关联表的主键名。

s_grade = db.Column(db.Integer, db.ForeignKey('grade.g_id'), nullable=True)
b)班级表中添加students字段:

在django中设置外键时只需要在要设置外键的表中添加外键,而不需要在被关联表中进行任何操作。但是在SQLAlchemy建模中,还需要在被关联的模型中添加关系。这里在Grade模型中新建了一个名叫students的属性用来表示当前班级中包含的学生列表。
格式:db.relationship(‘参数1’, backref='参数2', lazy=True)

students = db.relationship('Student', backref='stu', lazy=True)

如上所示,students被定义成一个db.relationship对象,该对象的构造函数由两部分组成:
>>>第一部分: 'Student'表示关系的另一端模型的名称.
>>>第二部分: 是一个名叫backref的参数,叫做反向关系,我们将其设置成'stu',它会像Student模型中添加一个名叫做stu的属性,这个属性可以替代s_grade访问Grade模型,但是它获取的是Grade模型的对象,而非Grade模型对应的g_id的值。

c)一对多的应用

实例1:通过学生id查询学生的信息,和该学生所在班级的信息
>>>a)视图

@grade.route('/selectgradebystu//')
def select_grade_by_stu(stuid):

    stu = Student.query.get(stuid)
    grade = stu.stu

    return render_template('student_grade.html', stu=stu, grade=grade)

>>>b)html页面解析


{% extends 'base_main.html' %}

{% block title %}
    根据学生查询班级
{% endblock %}

{% block content %}
    学生编号:{{ stu.s_id }}
    学生姓名:{{ stu.s_name }}
    学习年龄:{{ stu.s_age }}
    班级名称:{{ grade.g_name }}
{% endblock %}

>>>c)演示结果


Flask中数据库的应用_第1张图片

>>>d)比对数据库


Flask中数据库的应用_第2张图片
Flask中数据库的应用_第3张图片
image.png

实例2:通过班级id查找班级所有学生信息
>>>a)视图

@grade.route('/selectstubygrade//')
def select_stu_by_grade(gradeid):

    grade = Grade.query.get(gradeid)
    stus = grade.students

    return render_template('grade_student.html', grade=grade, stus=stus)

>>>b)html页面解析


{% extends 'base_main.html' %}

{% block title %}
    班级找学生
{% endblock %}

{% block content %}
    班级编号:{{ grade.g_id }}
    
    {% for stu in stus %}
  • 学生编号:{{ stu.s_id }} 学生姓名:{{ stu.s_name }} 学生年龄:{{ stu.s_age }}
  • {% endfor %}
{% endblock %}

>>>c)演示结果


Flask中数据库的应用_第4张图片

>>>d)比对数据库


Flask中数据库的应用_第5张图片
知识点:

1.想通过外键所在表查询被关联表的信息,不使用外键,而是使用backref指定的名称。


2.想通过被关联表查询外键所在表信息,使用被关联表中添加的字段名称即可。


5.多对多关系

多对多关系:假设存在一个学生表,和一个课程表,一个学生可以选择多门课程,一门课程可以被多个学生选择,那么学生和课程之间就是多对多的关系。
>>>学生表

class Student(db.Model):

    s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    s_name = db.Column(db.String(20), unique=True)
    s_age = db.Column(db.Integer, default=18)

    __tablename__ = 'student'

    def __init__(self, name, age):
        self.s_name = name
        self.s_age = age

>>>课程表

class Course(db.Model):
    c_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    c_name = db.Column(db.String(10), unique=True)

    __tablename__ = 'course'

    def __init__(self, name):
        self.c_name = name

flask中多对多关系仍使用定义一对多关系的 db.relationship() 方法进行定义,但在多对多关系中,增加了 secondary 参数,用于指定关联表。此处的关联表是需要单独创建的一个表,不是模型,SQLAlchemy 会自动接管这个表。多对多关系可以在关联的两个类中的任何一个类中定义, backref 参数会处理好关系的另一侧。

a)创建关联表

格式:db.Table('参数1‘, db.Column('参数2', db.参数3, db.ForeignKey('参数4')))
>>>参数1:关联表的名称
>>>参数2:字段名称
>>>参数3:数据类型
>>>参数4:外键名称,格式和一对多中格式相同

sc = db.Table('sc',
              db.Column('s_id', db.Integer, db.ForeignKey('student.s_id'), primary_key=True),
              db.Column('c_id', db.Integer, db.ForeignKey('course.c_id'), primary_key=True)
              )

b)在任意一个类中添加字段:

格式:db.relationship('参数1', secondary=参数2, backref='参数3')
>>>参数1:关联的另一个类名称
>>>参数2:关联表的表名称
>>>参数3:想要用另一个类调用这个类的信息时,就需要使用此参数,参数名称可自行定义。
如下在课程表中添加students字段,相当于给课程表添加了students属性,通过这个属性可以获取学生的信息,并且学生可以通过cou属性获取课程信息。

students = db.relationship('Student', secondary=sc, backref='cou')

c)多对多的应用

实例1:添加学生选课信息,一次只添加一门课程

>>>a)视图

@stu.route('/stucou/', methods=['GET', 'POST'])
def stu_cou():

    if request.method == 'GET':
        stus = Student.query.all()
        cous = Course.query.all()
        return render_template('stu_cou.html', stus=stus, cous=cous)
    else:
        s_id = request.form.get('student')
        c_id = request.form.get('course')

        stu = Student.query.get(s_id)
        cou = Course.query.get(c_id)

        cou.students.append(stu)
        db.session.add(cou)
        db.session.commit()

        return '学生选课成功'

>>>b)html页面解析


{% extends 'base_main.html' %}

{% block title %}
    学生课程信息
{% endblock %}

{% block extCSS %}
    
{% endblock %}

{% block content %}
    

学生1信息:



课程信息:


{% endblock %}

>>>c)演示结果


Flask中数据库的应用_第6张图片
Flask中数据库的应用_第7张图片
Flask中数据库的应用_第8张图片

>>>d)比对数据库
点击提交,会在数据库sc表中创建一条记录


Flask中数据库的应用_第9张图片
实例2:添加学生选课信息,一次添加多门课程

>>>a)视图

@stu.route('/stucou/', methods=['GET', 'POST'])
def stu_cou():

    if request.method == 'GET':
        stus = Student.query.all()
        cous = Course.query.all()
        return render_template('stu_cou.html', stus=stus, cous=cous)
    else:
        s_id = request.form.get('student')
        c_ids = request.form.getlist('course')

        stu = Student.query.get(s_id)
        for c_id in c_ids:
            cou = Course.query.get(c_id)
            cou.students.append(stu)
            db.session.add(cou)
            db.session.commit()

        return '学生选课成功'

>>>html页面解析


{% extends 'base_main.html' %}

{% block title %}
    学生课程信息
{% endblock %}

{% block extCSS %}
    
{% endblock %}

{% block content %}
    

学生1信息:



课程信息:



{% endblock %}

>>>演示结果


Flask中数据库的应用_第10张图片
Flask中数据库的应用_第11张图片

>>>比对数据库


实例3:学生查询选课信息

>>>a)视图

# 查询所有学生信息
@stu.route('/allstu/')
def all_stu():
    stus = Student.query.all()
    return render_template('all_stu.html', stus=stus)


# 查询学生选课信息
@stu.route('/selectcoubystu//')
def select_cou_by_stu(id):

    stu = Student.query.get(id)
    cous = stu.cou

    return render_template('stucourse.html', cous=cous, stu=stu)

>>>b)all_stu.html页面解析

{% extends 'base_main.html' %}

{% block title %}
    所有学生信息
{% endblock %}

{% block content %}
    
    {% for stu in stus %}
  • id:{{ stu.s_id }} 姓名:{{ stu.s_name }} 所选课程
  • {% endfor %}
{% endblock %}

>>>c)演示结果:


Flask中数据库的应用_第12张图片
Flask中数据库的应用_第13张图片

>>>比对数据库:


Flask中数据库的应用_第14张图片
实例4:删除学生的某条选课信息

>>>a)视图

@stu.route('/deletecoubyid///')
def delete_course_by_id(s_id, c_id):

    stu = Student.query.get(s_id)
    cou = Course.query.get(c_id)

    cou.students.remove(stu)
    db.session.commit()

    return redirect(url_for('stu.all_stu'))

>>>b)stucourse.html页面解析


{% extends 'base_main.html' %}

{% block title %}
    学生选课信息
{% endblock %}

{% block content %}
    {{ stu.s_name }}选课结果:
    
    {% for cou in cous %}
  • id:{{ cou.c_id }} 课程:{{ cou.c_name }} 删除
  • {% endfor %}
{% endblock %}

>>>c)演示结果


Flask中数据库的应用_第15张图片

>>>d)对比数据库
点击id=4的对应的删除,数据库中会删除对应数据,如下图,数据库中s_id=1 c_id=4 的记录已经被删除。


三、数据库的操作

1.创建表create_all()

@stu.route('/createtable/')
def create_db():
    db.create_all()
    return '创建成功'

2.删除表drop_all()

a)删除db中所有表

@stu.route('/dropalltable/')
def drop_all_table():
    db.drop_all()
    return '删除成功'

b)删除db中某个表

@stu.route('/droponetable/')
def drop_one_table():
    sql = 'delete table student'
    db.sesion.execute(sql)
    db.session.commit()
    return '删除成功'

3.插入 / 创建实例

>>>注意:最后必须要commit才会真正的在数据库中插入数据,否则数据只会保存在缓存区。为了保证事务的一致性,可以用使用try except捕获异常,如果没有执行commit,就回滚上一步操作。

a)模型未初始化
@stu.route('/createstu/')
def create_stu():

    stu = Student()
    stu.s_name = 'lp%d' % random.randrange(1000)
    stu.s_age = '%d' % random.randrange(20)

    db.session.add(stu)
    try:
        db.session.commit()
    except:
        db.session.rollback()
    return '创建学生成功'
b)模型初始化
@stu.route('/createstu/')
def create_stu():

    stu = Student(random.randrange(1000), random.randrange(20))

    db.session.add(stu)
    try:
        db.session.commit()
    except:
        db.session.rollback()
    return '创建学生成功'
c)插入多条记录 add_all([ ])
def create_stu():

        stu1 = Student(username1, age1)
        stu2 = Student(username2, age2)
        stu_list = [stu1, stu2]

        db.session.add_all(stus)
        try:
            db.session.commit()
        except:
            db.session.rollback()

    return '创建学生成功'

4.查询

a)查询所有数据

>>>方式1:模型.query.all()

用这种方式查询的结果是一个 list 而不是 queryset

@stu.route('/stulist/')
def stu_all():

    stus = Student.query.all()

    return render_template('stulist.html', stus=stus)
>>>方式2:原生sql语句 session.execute(sql)
@stu.route('/stulist/')
def stu_all():

    sql = 'select * from student;'
    stus = db.session.execute(sql)

    return render_template('stulist.html', stus=stus)

b)筛选数据

>>>方式1:使用sql语句
@stu.route('/studetail/')
def stu_detail():

    sql = 'select * from student where s_name="cy406" '
    stus = db.session.execute(sql)

    return render_template('stulist.html', stus=stus)
>>>方式2:使用 模型.query.属性
(1)filter(模型.字段.运算符 值)
@stu.route('/studetail/')
def stu_detail():

    stus = Student.query.filter(Student.s_name == 'cy253')

    return render_template('stulist.html', stus=stus)
运算符:

>>>==等于
实例:查询年龄等于18的学生

stus = Student.query.filter(Student.s_age == 18)

>>>__gt__大于
实例:查询年龄大于18的学生

stus = Student.query.filter(Student.s_age.__gt__(18))

>>>__lt__小于
实例:查询年龄小于18的学生

stus = Student.query.filter(Student.s_age.__lt__(18))

>>>__ge__大于等于
实例:查询年龄大于等于18的学生

stus = Student.query.filter(Student.s_age.__ge__(18))

>>>__le__小于等于
实例:查询年龄小于等于18的学生

stus = Student.query.filter(Student.s_age.__le__(18))

>>>in_([值, 值, 值]) 包含在某些值中
实例:查询年龄在16, 18, 20, 23 中的学生

stus = Student.query.filter(Student.s_age.in_([16, 18, 20, 23]))
(2)filter_by(字段 运算符 值)
stus = Student.query.filter_by(s_name='cy716')
(3)order_by('字段')

order_by默认升序,降序排列在字段前面加减号,如下:order_by('-字段')。
实例:按照年龄降序展示所有学生信息

stus = Student.query.order_by('-s_age')
(4)limit(显示条数)

实例:显示年龄最大的三个学生

stus = Student.query.order_by('-s_age').limit(3)
(5)offset(number) 跳过几条数据

实例:跳过前3条记录,显示2条记录,即显示第4条和第5条记录

stus = Student.query.order_by('-s_age').offset(3).limit(2)
(6)get(值)

flask中,get获取的是一个列表,如果每页获取到内容,get返回一个空列表,get中的参数对应主键字段。
实例:获取id为3的学生

stus = Student.query.get(3)
(7)and_ 并且

实例:查询 id 大于5 且 年龄为18 的学生

stus = Student.query.filter(and_(Student.s_age == 18, Student.s_id>5))
(8)or_ 或

实例:查询年龄大于18 或者 名字为 王小的学生

stus = Student.query.filter(or_(Student.s_age > 18, Student.s_name == '王小'))
(9)not_ 非

not_只能加一个限制条件
实例:查询年龄不是18的学生

stus = Student.query.filter(not_(Student.s_age == 18))

5.删除实例

@stu.route('/deletestu/')
def delete_stu():

    stu = Student.query.filter_by(s_id=1).first()
    db.session.delete(stu)
    db.session.commit()

    return redirect(url_for('stu.stu_all'))

6.更新/修改实例

>>>方式1:

@stu.route('/updatestu/')
def update_stu():

    stu = Student.query.filter_by(s_id=5).first()
    stu.s_name = '王小二'
    db.session.commit()

    return redirect(url_for('stu.stu_all'))

>>>方式2:update

@stu.route('/updatestu/')
def update_stu():

    Student.query.filter(Student.s_id == '1').update({'s_name': '王大锤'})
    db.session.commit()

    return redirect(url_for('stu.stu_all'))

你可能感兴趣的:(Flask中数据库的应用)