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 | 小整形 16為 | |
BigInteger | 大整形 | |
Float | float | 浮點數 |
String | str | 字元串 varchar |
Text | 長文本 | |
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:[email protected]: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:[email protected]: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'
其他都不做改變,基本思路是封裝到類,通過多繼承來實作方法的調用。