注意:在迁移前首先要开启数据库mysql
create_all()
对创建的模型数据进行迁移,这个方法只能用于首次创建,后面迁移需要用migrate(不建议用),建议用sql语句,orm实现的数据库迁移不是最有方式
@blue.route('create_db/') #设置路由信息
def create_db():
db.create_all() #调用flask方法
return '创建成功'
运行项目,浏览器中显示创建成功后,查看数据库可以看到此时生成刚创建的学生表
mysql> show tables;
+------------------+
| Tables_in_flask5 |
+------------------+
| student |
drop_all()
@blue.route('/drop_db/')
def drop_db():
# 删除表
db.drop_all()
return '删除成功'
语法:
类名.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)
基本格式:(注意等于号不同!!)
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)
【例】修改学生的信息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()
【例1】用filter
@blue.route('/delete_stu//')
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
第一种方式:
@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 '创建成功'
获取查询集
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)
获取的结果是学生的对象
模糊搜索like
%:代表一个或者多个
_:代表一个
Student.query.filter(Student.s_name.like('%张%'))
跳过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:
查询
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))
(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后面接(蓝图名.方法名)
Title
id
姓名
年龄
{% for stu in stus %}
{{ stu.id }}
{{ stu.s_name }}
{{ stu.s_age }}
{% endfor %}
当前{{ paginate.page }}页,共有{{ paginate.pages }}页
{% if paginate.has_prev %}
上一页
{% endif %}
{% for i in paginate.iter_pages() %}
{{ i }}
{% endfor %}
{% if paginate.has_next %}
下一页
{% endif %}
实现效果:
【例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
前端数据展示:
学生信息
{% for stu in stus %}
id:{{ stu.s_id }}
姓名:{{ stu.s_name }}
年龄:{{ stu.s_age }}
{% endfor %}
总页数: {{ paginate.pages }}
一共{{ paginate.total }}条数据
当前页数:{{ paginate.page }}
{% if paginate.has_prev %}
上一页:{{ paginate.prev_num }}
{% endif %}
{% if paginate.has_next %}
下一页:{{ paginate.next_num }}
{% endif %}
页码:{% for i in paginate.iter_pages() %}
{{ i }}
{% endfor %}