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')
db.execute('delete from user where 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)
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.create_all()
return '创建成功'
if __name__ == '__main__':
manager.run()
(5)增加数据
添加数据方式1
@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])
db.session.commit()
return '添加多条数据!'
添加数据方式2
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
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)更新与删除
@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)
return 'delete id=2'
(7) 拆分MVT
目录结构
project/
manage.py
ext.py
settings.py
app/
__init__.py
models.py
views.py
templates/
static/
ext.py SQLAlchemy扩展
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
蓝本view view.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='张三',info='个人信息')
db.session.add(u)
return 'insert success'
蓝本view models.py模型类
from ext import db
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__)
app.config.from_object(settings.Config)
db.init_app(app)
app.register_blueprint(view)
manager = Manager(app)
if __name__ == '__main__':
manager.run()
setting.py配置文件
class Config:
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
class Base:
def save(self):
try:
db.session.add(self)
db.session.commit()
except:
db.session.rollback()
@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()
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
在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('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'
其他都不做改变,基本思路是封装到类,通过多继承来实现方法的调用。