美文网首页
Flask中数据库的应用

Flask中数据库的应用

作者: kris_lp | 来源:发表于2018-05-16 17:12 被阅读0次

    一、配置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/<int:stuid>/')
    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)演示结果


    >>>d)比对数据库


    image.png

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

    @grade.route('/selectstubygrade/<int:gradeid>/')
    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 }}
        <ul>
        {% for stu in stus %}
            <li>
            学生编号:{{ stu.s_id }}
            学生姓名:{{ stu.s_name }}
            学生年龄:{{ stu.s_age }}
            </li>
        {% endfor %}
    
        </ul>
    
    {% endblock %}
    

    >>>c)演示结果


    >>>d)比对数据库


    知识点:

    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 %}
        <link rel="stylesheet" href="{{ url_for('static', filename='css/h3.css') }}">
    {% endblock %}
    
    {% block content %}
        <form action="" method="post">
    
            <h3>学生1信息:</h3>
            <br>
            <select name="student" id="">
                <option value="">请选择学生信息</option>
                {% for stu in stus %}
                    <option value="{{ stu.s_id }}">{{ stu.s_name }}</option>
                {% endfor %}
            </select>
            <br>
            <h3>课程信息:</h3>
            <select name="course" id="">
                <option value="">请选择课程信息</option>
                {% for cou in cous %}
                    <option value="{{ cou.c_id }}">{{ cou.c_name }}</option>
                {% endfor %}
            </select>
            <br>
            <input type="submit" value="提交">
    
        </form>
    
    {% endblock %}
    

    >>>c)演示结果


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


    实例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 %}
        <link rel="stylesheet" href="{{ url_for('static', filename='css/h3.css') }}">
    {% endblock %}
    
    {% block content %}
        <form action="" method="post">
    
            <h3>学生1信息:</h3>
            <br>
            <select name="student" id="">
                <option value="">请选择学生信息</option>
                {% for stu in stus %}
                    <option value="{{ stu.s_id }}">{{ stu.s_name }}</option>
                {% endfor %}
            </select>
            <br>
            <h3>课程信息:</h3>
            <select name="course" id="">
                <option value="">请选择课程信息</option>
                {% for cou in cous %}
                    <option value="{{ cou.c_id }}">{{ cou.c_name }}</option>
                {% endfor %}
            </select>
            <br>
            <select name="course" id="">
                <option value="">请选择课程信息</option>
                {% for cou in cous %}
                    <option value="{{ cou.c_id }}">{{ cou.c_name }}</option>
                {% endfor %}
            </select>
            <br>
            <input type="submit" value="提交">
    
        </form>
    
    {% endblock %}
    

    >>>演示结果


    >>>比对数据库


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

    >>>a)视图

    # 查询所有学生信息
    @stu.route('/allstu/')
    def all_stu():
        stus = Student.query.all()
        return render_template('all_stu.html', stus=stus)
    
    
    # 查询学生选课信息
    @stu.route('/selectcoubystu/<int:id>/')
    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 %}
        <ul>
        {% for stu in stus %}
            <li>
                id:{{ stu.s_id }}
                姓名:{{ stu.s_name }}
                <a href="/stu/selectcoubystu/{{ stu.s_id }}">所选课程</a>
            </li>
        {% endfor %}
    
        </ul>
    {% endblock %}
    

    >>>c)演示结果:


    >>>比对数据库:


    实例4:删除学生的某条选课信息

    >>>a)视图

    @stu.route('/deletecoubyid/<int:s_id>/<int:c_id>/')
    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 }}选课结果:
        <ul>
        {% for cou in cous %}
            <li>
                id:{{ cou.c_id }}
                课程:{{ cou.c_name }}
                <a href="/stu/deletecoubyid/{{ stu.s_id }}/{{ cou.c_id }}/">删除</a>
            </li>
        {% endfor %}
    
        </ul>
    {% endblock %}
    

    >>>c)演示结果


    >>>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中数据库的应用

          本文链接:https://www.haomeiwen.com/subject/usfpdftx.html