Flask作为一款MVC的框架,提供ORM的功能。学习模型之前,我们首先要明白下面三个问题。
1-什么是ORM?
中文为“对象关系映射”,通过ORM可以通过类的方式操作数据库,而不用再写原生的SQL语句,通过表映射成类,把行作为示例,把字段作为属性;ORM在进行对象操作的时候最终还会把对应的操作转换成原生的SQL语句。
2-为什么使用ORM?
随着项目的越来越大,采用原生SQL的方式,在代码中会出现大量的SQL,那么会出现如下问题:
- SQL语句重复使用率不高,越复杂的SQL语句条件就越多,代码也会越长,会出现很多相似的SQL语句;
- 很多SQL语句是在业务逻辑中拼出来的,如果有数据需要更改,就需要更改这些逻辑,这样会很容易漏掉某些SQL语句的修改;
- 写SQL语句时容易忽略web安全问题,给未来造成隐患;eg:SQL注入
3-ORM有哪些好处?
- 使用ORM做数据库开发可以有效的减少重复SQL语句的概率,写出来的模型也更加直观、清晰;
- 设计灵活,可轻松的写出复杂的SQL语句
- 可移植性,sqlaichemy封装了低层的数据库实践,支持多个关系数据库引擎,包括流行的mysql、sqllite等,可以很轻松的切换数据库;
- 性能损耗小,ORM换成低层数据库会有一些性能损耗,但从实际情况来看,该损耗比较小,如果不对性能有严格要求,结合综合开发效率,代码可阅读性带来的好处,带来的好处远远大于性能的损耗,项目越大越明显;
一、前期准备
- 在mysql中创建数据库:Create database 数据库名字 character set utf8
- 安装pymysql:pip install pymysql
- 安装flask-sqlaichemy:pip install Flask-SQLAlchemy
- 导入和配置
import os
from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 配置数据库连接
app.config['SQLAlCHEMY_DATABASE_URI']='mysql+pymysql://root:2016gfbcg!@127.0.0.1:3306/demo07'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
二、设计模型
1、常见字段类型
类型名称 | Python类型 | 说明 |
Integer | Int | 存储整型 |
Smallintege | Int | 小整型 |
Biginteger | Int | 长整型 |
Float | Float | 浮点型 |
String | Str | 字符串(不定长varchar) |
Text | Str | 大型文本 |
Bollean | Bool | 布尔类型 |
Date | Datatime.date | 日期 |
Time | Datatime.time | 时间 |
Datatime | Datatime.datatime | 日期和时间 |
2、可约束条件
选项 | 说明 |
Primary_key | 是否设置主键,默认为False |
Unique | 是否设置唯一索引,默认为false |
Index | 是否设置常规索引,默认为false |
Nullable | 是否可以为空,默认为True |
default | 设置默认值 |
3、注意事项
- Flask-sqlaichemy要求每个模型都要有一个主键,否则报错;
- 默认可以为空,设置默认值的时候并不是更改表结果的默认值,而是在你没有给当前值的时候会把默认值作为值进行传入
三、创建模型
1、创建模型类
eg:user类
# 创建模型类
class User(db.Model, DB_Base):
__tablename__ = 'user' # 起表名,不起默认为类名
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(10), default='guofubin', index=True)
age = db.Column(db.Integer, default=18)
sex = db.Column(db.Boolean, default=True)
info = db.Column(db.String(50), default='个人简介')
def __str__(self):
return 'username:{}'.format(self.username)
2、创建数据表
# 创建表
@app.route('/create/')
def create():
db.create_all()
return '创建表'
3、删除数据表
# 删除表
@app.route('/drop/')
def drop():
db.drop_all()
return '删除表'
四、数据的增删改查
1、添加数据
添加一条数据
# 添加一条数据
@app.route('/insert_one/')
def insert_one():
"""方法一:
try:
data=User()
data.username='lucky'
data.age=25
data.sex=False
data.info='我就是我,就是这么强'
db.session.add(data)
db.session.commit()
except:
db.session.rollback()
# 方法二
try:
data=User(username='lucky')
db.session.add(data)
db.session.commit()
except:
db.session.rollback()
"""
return '添加一天数据'
添加多条数据
# 插入多条数据
@app.route('/insert_many/')
def insert_many():
try:
u1 = User(username='张三', sex=True, age=20)
u2 = User(username='李四', sex=False, age=30)
db.session.add_all([u1, u2])
db.session.commit()
except:
db.session.rollback()
return '添加多条数据'
2、删除数据
# 数据的删除
@app.route('/delete/')
def delete():
u = User.query.get(4)
db.session.delete(u)
db.session.commit()
return '删除'
3、修改数据
# 数据的修改
@app.route('/update/')
def update():
try:
u = User.query.get(1)
u.age = 2
db.session.add(u)
db.session.commit()
except:
db.session.rollback()
return '修改数据'
4、查询数据
# 查询数据
@app.route('/select/')
def select():
u = User.query.get(1) # 通过主键key进行筛选
print(u)
print(u.age)
return '查询数据'
五、自定义增删改查模型类
1、封装模型基类
# 自定义封装模型基类
class DB_Base:
# 添加一条数据,对象方法
def save(self):
try:
db.session.add(self)
db.session.commit()
except:
db.session.rollback()
# 添加多条数据,静态方法
@staticmethod
def save_all(*args):
try:
db.session.add_all(args)
db.session.commit()
except:
db.session.rollback()
# 删除数据
def delete(self):
try:
db.session.delete(self)
db.session.commit()
return True
except:
db.session.rollback()
return False
2、模型类继承基类
# 创建模型类
class User(db.Model, DB_Base):
__tablename__ = 'user' # 起表名,不起默认为类名
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(10), default='guofubin', index=True)
age = db.Column(db.Integer, default=18)
sex = db.Column(db.Boolean, default=True)
info = db.Column(db.String(50), default='个人简介')
def __str__(self):
return 'username:{}'.format(self.username)
3、操作模型
通过SQLAlchemy操作模型,进而操作数据库
# 添加一条数据
@app.route('/insert_one/')
def insert_one():
u = User(username='lucky')
u.save()
return '添加一天数据'
# 插入多条数据
@app.route('/insert_many/')
def insert_many():
try:
u1 = User(username='张三', sex=True, age=20)
u2 = User(username='李四', sex=False, age=30)
User.save_all(u1,u2)
except:
db.session.rollback()
return '添加多条数据'
# 查询数据
@app.route('/select/')
def select():
u = User.query.get(1) # 通过主键key进行筛选
print(u)
print(u.age)
return '查询数据'
# 数据的修改
@app.route('/update/')
def update():
try:
u = User.query.get(1)
u.age = 2
u.save()
except:
db.session.rollback()
return '修改数据'
# 数据的删除
@app.route('/delete/')
def delete():
u = User.query.get(4)
u.delete()
return '删除'
六、数据库操作
查询集即为查询数据的集合;主要分两种:一种属于原始查询集,通过“类名.query”得到原始查询集;另一种属于数据查询集,通过过滤器方法过滤查询集或亚数据查询集;主要特点为可以进行链式调用,下面介绍相关函数:
1、all()
查询所有,通过列表方式返回
users=User.query.all()
2、filter()
条件筛选数据集。格式:filter(类名.属性名 运算符 值)
users = User.query.filter(User.sex==False).filter(User.age>=18)
3、filter_by()
只支持间断属性查询。格式:filter_by(属性名1=值1,属性名2=值2)
users=User.query.filter_by(sex=True,age=18)
4、offset(num)和limit(num)
offset(num1):表示偏移量,从num1条数据开始算起;
limit(num2):表示输出量,默认从第一天数据算起,输出num2条数据
offset(num1).limit(num2)从num1条数据算起输出num2条数据
users = User.query.offset(2).limit(3) # 偏移2条取3条
5、order()
格式:order(类名.属性名),默认按指定字段升序排列,如果想要降序排列则在类名前加上“-”
users=User.query.order_by(User.age) # 升序排列
users = User.query.order_by(-User.age) # 降序排列
6、first()
取第一条数据,返回对象并不是可迭代对象。
users = User.query.first() # 取第一条数据
7、get(key)
通过主键获取,返回对象不是可迭代对象,如果获取不到返回None;
users = User.query.get(2)
8、contains()
格式:contains("四"),获取指定属性中包含“四”这个词的数据