天天看點

Flask入門資料庫架構flask-SQLAlchemy(十)

​ 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

注意:

  1. username 和 password 表示登入資料庫的使用者名和密碼
  2. hostname 表示 SQL 服務所在的主機,可以是本地主機(localhost)也可以是遠端伺服器
  3. database 表示要使用的資料庫 , SQLite 資料庫不需要使用伺服器,它使用硬碟上的檔案名作為 database

ORM使用的優點:

  1. 增加少sql的重複使用率
  2. 使表更加的可讀性
  3. 可移植性

(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'           

其他都不做改變,基本思路是封裝到類,通過多繼承來實作方法的調用。