Flask高级应用06---模型的CRUD和高级用法

一、数据映射(数据库crud基础操作)

注意:在迁移前首先要开启数据库mysql

1.创建模型==create_all()

对创建的模型数据进行迁移,这个方法只能用于首次创建,后面迁移需要用migrate(不建议用),建议用sql语句,orm实现的数据库迁移不是最有方式

@blue.route('create_db/')     #设置路由信息
def create_db():               
    db.create_all()			#调用flask方法
    return '创建成功'         

运行项目,浏览器中显示创建成功后,查看数据库可以看到此时生成刚创建的学生表

mysql> show tables;
+------------------+
| Tables_in_flask5 |
+------------------+
| student          |

2.删除表(谨慎使用!!)==drop_all()

@blue.route('/drop_db/')
def drop_db():
    # 删除表
    db.drop_all()
    return '删除成功'

3.给学生表添加信息:

语法:

类名.query.xxx

获取查询集:

all()

filter(类名.属性名==xxx)

filter_by(属性名=xxx)

数据操作:

在事务中处理,数据插入

db.session.add(object)

db.session.add_all(list[object])

db.session.delete(object)

db.session.commit()    #提交事务,使用commit提交我们的添加数据的操作

修改和删除基于查询

(1)添加一条学生信息

@blue.route('/create_stu/')
def create_stu():
    #实现创建
    stu = Student()
    stu.s_name = '小明'
    db.session.add(stu)
    db.session.commit()
    return '创建学生信息成功'

提交事务,使用commit提交我们的添加数据的操作

**方式优化:**封装一个save()方法

在模型module.py中定义一个方法

    def save(self):
        db.session.add(self)
        db.session.commit()

在视图中直接调用save方法:

@blue.route('/create_stu/')
def create_stu():
    #实现创建方法二:模型中单独定义一个方法
    stu = Student()
    stu.s_name = '小明1'
    stu.save()
    return '创建学生信息成功'

(2)批量添加—创建多个学生信息

定义列表,然后用for循环

@blue.route('/create_stu_all/')
def create_stu_all():
    names = ['宋江','武松','李逵','林冲','鲁智深']
    for name in names:
        stu = Student()
        stu.s_name = name
        #方式一:
        stu.save()      #调用封装的save方法  
    return '批量创建成功'

优化:传入列表,用add_all,(推荐)

@blue.route('/create_stu_all/')
def create_stu_all():
    names = ['宋江','武松','李逵','林冲','鲁智深']
    stu_list = []
    for name in names:
        stu = Student()
        stu.s_name = name
        stu_list.append(stu)        #append给列表添加内容
        db.session.add_all(stu_list)
        db.session.commit()
    return '批量创建成功'

效果添加成功:

mysql> select * from student;
+----+--------+-------+
| id | s_name | s_age |
+----+--------+-------+
|  1 | 小明   |    19 |
|  2 | 宋江   |    19 |
|  3 | 武松   |    19 |
|  4 | 李逵   |    19 |
|  5 | 林冲   |    19 |
|  6 | 鲁智深 |    19 |
+----+--------+-------+
6 rows in set (0.07 sec)

4.查询信息==过滤(filter、filter_by)

基本格式:(注意等于号不同!!)

filter(类名.属性名==xxx)

filter_by(属性名=xxx)

【例】

@blue.route('/sel_stu/')
def sel_stu():
    #查询,filter(),filter_by
    #返回类型是querybase
    stu = Student.query.filter(Student.s_name =='宋江')
    stu = Student.query.filter_by(s_name='武松')
    return '查询成功'

注意; .all()后面不能再接filter了,因为获取的是列表,django中可以后面接filter,因为获取的是queryset,是可以通过下标拿值的

【例】将学生的全部信息获取到,并且返回给页面,在页面中使用for循环去解析即可

@blue.route("/getstudents/")
def get_students():
    students = Student.query.all()
    return render_template("StudentList.html", students=students)

【例】获取s_id=1的学生的信息

写法1:

students = Student.query.filter(Student.id==1)

写法2:

students = Student.query.filter_by(id=2)

注意:filter中可以接多个过滤条件

写法3:(直接用sql语句)===excute

sql = 'select * from student where id=1'
students = db.session.execute(sql)

5.修改学生信息

【例】修改学生的信息update

写法1:

students = Student.query.filter_by(id=3).first()
students.s_name = '哈哈'
db.session.commit()

写法2:

Student.query.filter_by(s_id=3).update({'s_name':'娃哈哈'})

db.session.commit()

6.删除学生信息

【例1】用filter

@blue.route('/delete_stu/<int:id>/')
def delete_stu(id):
    stu = Student.query.filter(Student.id ==id).first()
    db.session.delete(stu)
    db.session.commit()
    return '删除成功'

运行后在url中输入

。。。。./delete_stu/2    运行成功可以看到数据库表中第二条数据删除

【例2】删除一个学生的信息用filter_by

写法1:

stu = Student.query.filter_by(id=2).first()  
db.session.delete(stu)
db.session.commit()

写法2:

students = Student.query.filter_by(id=1).all()
db.session.delete(students[0])
db.session.commit()

注意:filter_by后的结果是一个list的结果集

重点注意:在增删改中如果不commit的话,数据库中的数据并不会更新,只会修改本地缓存中的数据,所以一定需要db.session.commit()

【科普】GIL

二、 深入数据库增删改查

定义模型,并定义初始化的函数:

class Student(db.Model):

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

    __tablename__ = "student"

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

1、批量增加

第一种方式–add_all:

@blue.route('/createstus/')
def create_users():
    stus = []
    for i in range(5):
		# 实例化Student的对象
        s = Student()
		# 对象的属性赋值
        s.s_name = '张三%s' % random.randrange(10000)
        s.s_age = '%d' % random.randrange(100)
        stus.append(s)
	# 添加需要创建的数据
    db.session.add_all(stus)
	# 提交事务到数据库
    db.session.commit()

    return '创建成功'

注:在创建单条数据的时候使用db.session.add(),在创建多条数据的时候使用db.session.add_all()

第二种方式:

@blue.route('/createstus/')
def create_users():
    stus = []
    for i in range(5):
		# 使用类的初始化去创建Student对象
        s = Student('张三%s' % random.randrange(10000),
                    '%d' % random.randrange(100))
        stus.append(s)

    db.session.add_all(stus)
    db.session.commit()

    return '创建成功'

2、 使用运算符查询

获取查询集

filter(类名.属性名.运算符(‘xxx’))

filter(类名.属性 数学运算符  值)

运算符:

contains: 包含
startswith:以什么开始
endswith:以什么结束
in_:在范围内
like:模糊
__gt__: 大于
__ge__:大于等于
__lt__:小于
__le__:小于等于

筛选:

offset()

limit()

order_by()

get()

first()

paginate()

逻辑运算:

与
	and_
	filter(and_(条件),条件…)

或
	or_
	filter(or_(条件),条件…)

非
	not_
	filter(not_(条件),条件…)

【例1】查询学生的id为3,4,5,6,16的的学生信息,使用in_逻辑运算

 @blue.route('/getstubyids/')
 def get_stu_by_ids():

 	students = Student.query.filter(Student.s_id.in_([3,4,5,6,16]))
 	return render_template('StudentList.html', students=students)

【例2】查询学生的年龄小于18岁的学生的信息

 Student.query.filter(Student.s_age < 18)

【例3】查询学生的年龄小于18岁的学生的信息,__lt__小于

 students = Student.query.filter(Student.s_age.__lt__(15))

【例4】查询学生的年龄小于等于18岁的学生的信息,__le__小于等于

 students = Student.query.filter(Student.s_age.__le__(15))

【例5】查询学生的姓名以什么开始或者以什么结尾的学生的信息startswith和endswith

 students = Student.query.filter(Student.s_name.startswith('张'))
 students = Student.query.filter(Student.s_name.endswith('2'))

【例6】查询id=4的学生的信息

 Student.query.get(4)
 获取的结果是学生的对象

3、模糊查询

模糊搜索like

 %:代表一个或者多个
 _:代表一个
 
 Student.query.filter(Student.s_name.like('%张%')) 

4、排序查询

跳过offset几个信息,截取limit结果的几个值

# 按照id降序排列
stus = Student.query.order_by('-s_id')

# 按照id升序排列
stus = Student.query.order_by('s_id')
stus = Student.query.order_by(asc('s_id'))
stus = Student.query.order_by('s_id asc')

# 按照id降序获取三个
stus = Student.query.order_by('-s_id').limit(3)
stus = Student.query.order_by('s_id desc').limit(3)

from sqlalchemy import desc
stus = Student.query.order_by(desc('s_id')).limit(3)

# 获取年龄最大的一个
stus = Student.query.order_by('-s_age').first()

# 跳过3个数据,查询5个信息
stus = Student.query.order_by('-s_age').offset(3).limit(5)

# 跳过3个数据
stus = Student.query.order_by('-s_age').offset(3)

# 获取id等于24的学生
stus = Student.query.filter(Student.s_id==24)
stus = Student.query.get(24)

例子3:

  1. 查询

    from sqlalchemy import and_, or_, not_

    查询多个条件

    stus = Student.query.filter(Student.s_age18, Student.s_name’雅典娜’)

    and_ 并且条件

    stus = Student.query.filter(and_(Student.s_age18, Student.s_name’雅典娜’))

    or_ 或者条件

    stus = Student.query.filter(or_(Student.s_age18, Student.s_name’火神’))

    not_ 非

    stus = Student.query.filter(not_(Student.s_age18), Student.s_name’火神’)

    查询姓名不包含’可爱‘,并且年龄不等于12的学生

    stus = Student.query.filter(not_(Student.s_name.contains(‘可爱’)), not_(Student.s_age == 12))

5、分页查询

(1)分页的四种方式:

(1)offset+limit
(2)切片
(3)sql语句
(4)paginate()方法

(2)分页的属性

在这里插入图片描述

【例】在视图中定义路由和方法(这里将前三种方式注释掉,采用paginate分页)

#app/views


@blue.route('/paginate/')
def stu_paginate():
    page = int(request.args.get('page', 1))
    """
    # 1. offset+limit
    stus = Student.query.offset((page-1) * 2).limit(2)
    # 2. 切片
    stus = Student.query.all()[(page-1)*2:page*2]
    # 3. sql语句
    sql = 'select * from student limit %s,%s' % ((page-1)*2, 2)
    stus = db.session.execute(sql)
    """
    # 4. paginate()方法
    paginate = Student.query.paginate(page, 2)
    stus = paginate.items
    return render_template('stus.html', stus=stus, paginate=paginate)

在模板中展示内容

注意:url_for后面接(蓝图名.方法名)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <table>
        <thead>
            <th>id</th>
            <th>姓名</th>
            <th>年龄</th>
        </thead>
        <tbody>
            {% for stu in stus %}
                <tr>
                    <td>{{ stu.id }}</td>
                    <td>{{ stu.s_name }}</td>
                    <td>{{ stu.s_age }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    <br>
 <p>当前{{ paginate.page }}页,共有{{ paginate.pages }}页</p>

     {% if paginate.has_prev %}
        <a href="{{ url_for('app.stu_paginate') }}?page={{ paginate.prev_num }}">上一页</a>
    {% endif %}
     {% for i in paginate.iter_pages() %}
        <a href="{{ url_for('app.stu_paginate') }}?page={{ i }}">{{ i }}</a>
    {% endfor %}

    {% if paginate.has_next %}
        <a href="{{ url_for('app.stu_paginate') }}?page={{ paginate.next_num }}">下一页</a>
    {% endif %}

</body>
</html>

实现效果:
在这里插入图片描述

【例2】后端数据处理:

# 方法一:手动实现分页,使用offset和limit
page = int(request.args.get('page', 1))
stus = Student.query.offset((page-1)*5).limit(5)

# 方法二: 使用切片[:]
s_page = (page - 1)*5
e_page = page * 5
stus = Student.query.all()[s_page: e_page]

# 方法三:使用paginate
# 查询第几页的数据	
page = int(request.args.get('page', 1))

# 每一页的条数多少,默认为10条
per_page = int(request.args.get('per_page', 10))

# 查询当前第几个的多少条数据
paginate = Student.query.order_by('-s_id').paginate(page, per_page, error_out=False)

stus = paginate.items

前端数据展示:

<h2>学生信息</h2>
{% for stu in stus %}
    id:{{ stu.s_id }}
    姓名:{{ stu.s_name }}
    年龄:{{ stu.s_age }}
    <br>
{% endfor %}
<br>
总页数: {{ paginate.pages }}
<br>
一共{{ paginate.total }}条数据
<br>
当前页数:{{ paginate.page }}
<br>
{% if paginate.has_prev %}
    <a href="/stupage/?page={{ paginate.prev_num }}">上一页</a>:{{ paginate.prev_num }}
{% endif %}

{% if paginate.has_next %}
    <a href="/stupage/?page={{ paginate.next_num }}">下一页</a>:{{ paginate.next_num }}
{% endif %}
<br>

<br>
页码:{% for i in  paginate.iter_pages() %}
        <a href="/stupage/?page={{ i }}">{{ i }}</a>
    {% endfor %}

猜你喜欢

转载自blog.csdn.net/ZZQHELLO2018/article/details/83146374