Web程序开发中最重要的莫过于关系型数据库,即SQL 数据库,另外文档数据库(如 mongodb)、键值对数据库(如 redis)慢慢变得流行.
原因 : 我们不直接使用这些数据库引擎提供的 Python 包,而是使用对象关系映射(Object-Relational Mapper, ORM)框架,是因为它将低层的数据库操作指令抽象成高层的面向对象操作。也就是说,如果我们直接使用数据库引擎,我们就要写 SQL 操作语句,但是,如果我们使用了 ORM 框架,我们对诸如表、文档此类的数据库实体就可以简化成对 Python 对象的操作。
(1) Flask - SQLAlchemy
Flask使用的ORM框架为 SQLAlchemy,数据库采用了URL指定,下面我们列举几种数据库引擎:
数据库引擎 | URL指定 |
---|---|
MySQL | mysql://username:password@hostname/database |
Postgres | postgresql://username:password@hostname/database |
SQLite (Unix) | sqlite:absolute/path/to/database |
SQLite (Windows) | sqlite:///c:/absolute/path/to/database |
注意:
- username 和 password 表示登录数据库的用户名和密码
- hostname 表示 SQL 服务所在的主机,可以是本地主机(localhost)也可以是远程服务器
- database 表示要使用的数据库 , SQLite 数据库不需要使用服务器,它使用硬盘上的文件名作为 database
ORM使用的优点:
- 增加少sql的重复使用率
- 使表更加的可读性
- 可移植性
(2) SQLAlchemy操作sql原生
安装操作数据库的模块
pip3 install pymysql
安装 flask-sqlalchemy
sudo pip3 install flask-sqlalchemy
配置路径
DB_URI = ‘mysql+pymysql://root:password@host:port/database’
下面先看下sqlalchemy操作的写法:
from sqlalchemy import create_engine
HOST = '127.0.0.1'
USERNAME = 'root'
PASSWORD = '123456'
DATABASE = 'demo' #数据库名
PORT = 3306
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOST,PORT,DATABASE)
#创建引擎
engine = create_engine(DB_URI)
with engine.connect() as db:
data = db.execute('select * from user') #从user表中获取全部数据
db.execute('delete from user where id=1') #删除id=1的数据
(3) 设计数据表
1 字段类型
类型名 | python中的类型 | 说明 |
---|---|---|
Integer | int | 存储整形 32位 |
SmallInteger | int | 小整形 16为 |
BigInteger | int | 大整形 |
Float | float | 浮点数 |
String | str | 字符串 varchar |
Text | str | 长文本 |
Boolean | bool | bool值 |
Date | datetimedate | 日期 |
Time | datetime.time | 时间 |
datetime | datetime.datetime | 时间日期 |
2 可选条件
选项 | 说明 |
---|---|
primary_key | 主键, 如果设为True,表示主键 |
unique | 唯一索引 ,如果设为True,这列唯一 |
index | 常规索引, 如果设为True,创建索引,提升查询效率 |
nullable | 是否可以为null 默认True |
default | 默认值 |
(4)在flask中使用ORM模型
下面我们使用ORM模型
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:20111673@127.0.0.1:3306/demo'
db = SQLAlchemy(app) #
manager = Manager(app)
#创建User用户,表名为user
class User(db.Model):
__table__name = 'user'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(20),index=True)
sex = db.Column(db.Boolean,default=True)
info = db.Column(db.String(50))
# 定义一个视图函数
@app.route('/create')
def create():
# db.drop_all() #删除仅为模型表
db.create_all() #创建模型表
return '创建成功'
if __name__ == '__main__':
manager.run()
(5)增加数据
添加数据方式1
#方式1
# sqlalchemy默认开启了事务处理
@app.route('/insert/')
def insert():
try:
u = User(username='WANGWU',info='personal WANGWU message')
db.session.add(u) #添加数据对象
db.session.commit() #事务提交
except:
db.session.rollback()#事务回滚
return '添加单条数据!'
@app.route('/insertMany/')
def insertMany():
u1 = User(username='name1',info='personal name1 message')
u2 = User(username='name2',info='personal name2 message')
db.session.add_all([u1,u2]) #以add_all(数据对象列表)
db.session.commit() #
return '添加多条数据!'
添加数据方式2
#方式2
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True #在app设置里开启自动提交
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False #关闭数据追踪,避免内存资源浪费
@app.route('/insertMany/')
def insertMany():
u1 = User(username='name1',info='personal name1 message')
u2 = User(username='name2',info='personal name2 message')
db.session.add_all([u1,u2])
return '提交多条数据'
(6)更新与删除
# 类名.query 返回对应的查询集
# 类名.query.get(查询条件) 返回对应的查询对象
@app.route('/update/')
def update():
u = User.query.get(1)
u.username = 'update name' #更新内容
db.session.add(u) #进行添加
return 'update'
# 删除数据
@app.route('/delete/')
def delete():
u = User.query.get(2) #找到对应的查询集对象
db.session.delete(u) # 删除对应的u对象
return 'delete id=2'
(7) 拆分MVT
目录结构
project/
manage.py #启动项存放
ext.py #作为当前sqlalchemy扩展
settings.py #配置存放
app/
__init__.py
models.py #应用models.py
views.py #应用视图views.py
templates/ #模板目录
static/ #静态文件目录
ext.py SQLAlchemy扩展
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy() #实例化db对象
蓝本view view.py视图函数
from flask import Blueprint
from .models import User
from ext import db
#创建蓝本view
view = Blueprint('view',__name__)
#定义视图函数
@view.route('/')
def index():
return 'index'
@view.route('/insert/')
def insert():
u = User(username='张三',info='个人信息')
db.session.add(u)
return 'insert success'
蓝本view models.py模型类
from ext import db #导入db
#构建User模型类
class User(db.Model,Base):
__table__name = 'user'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(20),index=True)
sex = db.Column(db.Boolean,default=True)
info = db.Column(db.String(50))
manage.py启动项
from flask import Flask
from flask_script import Manager
from ext import db
import settings
from app.view import view
app = Flask(__name__)
#将系统配置项Config类加载到app
app.config.from_object(settings.Config)
#通过db对象将app初始化
db.init_app(app)
#将蓝图view注册进app
app.register_blueprint(view)
manager = Manager(app)
if __name__ == '__main__':
manager.run()
setting.py配置文件
class Config:
#设置mysql+pymysql的连接
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:20111673@127.0.0.1:3306/demo'
#加密设置
SECRETE_KEY = 'secret_key'
#关闭数据追踪
SQLALCHEMY_TRACK_MODIFICATIONS = False
#开启提交
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
前面我们采用系统的每次自动提交session 即SQLALCHEMY_COMMIT_ON_TEARDOWN
但是如果想自己定义提交方式,同时不想传入关键字参数,那么该怎样入手呢?这里提供一种思路
(8) 自定义增删改类
我们对模型类进行了修改,models.py 内容如下:
from ext import db
#定义了base基类
class Base:
def save(self):
try:
db.session.add(self) #self实例化对象代表就是u对象
db.session.commit()
except:
db.session.rollback()
#定义静态类方法接收List参数
@staticmethod
def save_all(List):
try:
db.session.add_all(List)
db.session.commit()
except:
db.session.rollback()
#定义删除方法
def delete(self):
try:
db.session.delete(self)
db.session.commit()
except:
db.session.rollback()
#定义模型user类
class User(db.Model,Base):
__table__name = 'user'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(20),index=True)
sex = db.Column(db.Boolean,default=True)
info = db.Column(db.String(50))
#
def __init__(self,username='',info='',sex=True):
self.username = username
self.info = info
self.sex = sex
#注意:
#原实例化: u = User(username='张三',info='个人信息')
#现实例化: u = User('李四','李四个人信息')
在views.py中使用
from flask import Blueprint
from .models import User
from ext import db
view = Blueprint('view',__name__)
@view.route('/')
def index():
return 'index'
#插入单条数据
@view.route('/insert/')
def insert():
# u = User(username='test',info='default')
u = User('xiaomeng','default')
u.save()
db.session.add(u)
return 'insert success'
#保存多条数据
@view.route('/saveMany/')
def saveMany():
u1 = User('zhan123','default123')
u2 = User('li123','default message')
User.save_all([u1,u2])
return 'add many'
#删除数据
@view.route('/delete/')
def delete():
u = User.query.get(1) #获取查询集
u.delete()
return 'delete message'
其他都不做改变,基本思路是封装到类,通过多继承来实现方法的调用。