1. 程式人生 > >flask學習筆記(-資料庫)

flask學習筆記(-資料庫)

Python 資料庫框架

大多數的資料庫引擎都有對應的 Python 包,包括開源包和商業包。Flask 並不限制你使用何種型別的資料庫包,因此可以根據自己的喜好選擇使用 MySQL、Postgres、SQLite、Redis、MongoDB 或者 CouchDB。

如果這些都無法滿足需求,還有一些資料庫抽象層程式碼包供選擇,例如SQLAlchemyMongoEngine。你可以使用這些抽象包直接處理高等級的 Python 物件,而不用處理如表、文件或查詢語言此類的資料庫實體。

選擇資料庫框架的因素:

  • 易用性。抽象層,也稱為物件關係映 射(Object-Relational Mapper,ORM) 或 對 象 文 檔 映 射(Object-Document Mapper,ODM),在使用者不知覺的情況下把高層的面向物件操作轉換成低層的資料庫指令。
  • 效能。ORM 和 ODM 把物件業務轉換成資料庫業務會有一定的損耗。真正的關鍵點在於如何選擇一個能直接操作低層資料庫的抽象層,以防特定的操作需要直接使用資料庫原生指令優化。
  • 可移植性。必須考慮其是否能在你的開發平臺和生產平臺中使用。
  • Flask整合度
  • 安裝
pip install flask-sqlalchemy

使用URL制定資料庫

資料庫引擎 URL
MySQL mysql://username:[email protected]/database
Postgres postgresql://username:[email protected]
/database
SQLite(Unix) sqlite:////absolute/path/to/database
SQLite(Windows) sqlite:///c:/absolute/path/to/database

SQLite 數 據 庫 不 需 要 使 用 服 務 器, 因 此 不 用 指 定 hostname 、 username 和 password 。URL 中的 database 是硬碟上檔案的檔名。

  • 配置
    程式使用的資料庫 URL 必須儲存到 Flask 配置物件的 SQLALCHEMY_DATABASE_URI 鍵中

配置物件中還有一個很有用的選項,即 SQLALCHEMY_COMMIT_ON_TEARDOWN 鍵,將其設為 True時,每次請求結束後都會自動提交資料庫中的變動

from flask.ext.sqlalchemy import SQLAlchemy
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
db = SQLAlchemy(app)
  • 定義模型
class Role(db.Model):
    __tablename__ = 'roles'#__tablename__ 定義在資料庫中使用的表名
    id = db.Column(db.Integer, primary_key=True)#primary_key如果設為 True ,這列就是表的主鍵.如果沒有定義 __tablename__ ,SQLAlchemy 會使用一個預設名字
    name = db.Column(db.String(64), unique=True)
    def __repr__(self):
        return '<Role % r>' % self.name
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    def __repr__(self):
        return '<User % r>' % self.username

最常用的SQLAlchemy列型別

型別名 Python型別 說 明
Integer int 普通整數,一般是 32 位
SmallInteger int 取值範圍小的整數,一般是 16 位
BigInteger int 或 long 不限制精度的整數
Float float 浮點數
Numeric decimal.Decimal 定點數
String str 變長字串
Text str 變長字串,對較長或不限長度的字串做了優化
Unicode unicode 變長 Unicode 字串
UnicodeText unicode 變長 Unicode 字串,對較長或不限長度的字串做了優化
Boolean bool 布林值
Date datetime.date 日期
Time datetime.time 時間
DateTime datetime.datetime 日期和時間
Interval datetime.timedelta 時間間隔
Enum str 一組字串
PickleType 任何 Python 物件 自動使用 Pickle 序列化
LargeBinary str 二進位制檔案

最常使用的SQLAlchemy列選項

選項名 說 明
primary_key 如果設為 True ,這列就是表的主鍵
unique 如果設為 True ,這列不允許出現重複的值
index 如果設為 True ,為這列建立索引,提升查詢效率
nullable 如果設為 True ,這列允許使用空值;如果設為 False ,這列不允許使用空值
default 為這列定義預設值

關係表達

關係型資料庫使用關係把不同表中的行聯絡起來。

  • 一對多
class Role(db.Model):
    # ...
    users = db.relationship('User', backref='role')#新增到 Role 模型中的 users 屬性代表這個關係的面向物件視角。對於一個 Role 類的例項,其 users 屬性將返回與角色相關聯的使用者組成的列表。db.relationship() 的第一個引數表,如果模型類尚未定義,可使用字串形式指定。db.relationship() 中的 backref 引數向 User 模型中新增一個 role 屬性,從而定義反向關係。這一屬性可替代 role_id 訪問 Role 模型,此時獲取的是模型物件
class User(db.Model):
    # ...
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))#關係使用 users 表中的外來鍵連線了兩行。新增到 User 模型中的 role_id 列被定義為外來鍵,就是這個外來鍵建立起了關係。傳給 db.ForeignKey() 的引數 'roles.id' 表明,這列的值是 roles 表中行的 id 值。

db.relationship() 都能自行找到關係中的外來鍵,但有時卻無法決定把哪一列作為外來鍵。如果 User 模型中有兩個或以上的列定義為 Role 模型的外來鍵,SQLAlchemy 就不知道該使用哪列。如果無法決定外來鍵,你就要為 db.relationship() 提供額外引數,從而確定所用外來鍵

常用的SQLAlchemy關係選項

選項名 說 明
backref 在關係的另一個模型中新增反向引用
primaryjoin 明確指定兩個模型之間使用的聯結條件。只在模稜兩可的關係中需要指定
lazy 指定如何載入相關記錄。可選值有 select (首次訪問時按需載入)、 immediate (源物件載入後就載入)、 joined (載入記錄,但使用聯結)、 subquery (立即載入,但使用子查詢),noload (永不載入)和 dynamic (不載入記錄,但提供載入記錄的查詢)
uselist 如果設為 Fales ,不使用列表,而使用標量值
order_by 指定關係中記錄的排序方式
secondary 指定 多對多 關係中關係表的名字
secondaryjoin SQLAlchemy 無法自行決定時,指定多對多關係中的二級聯結條件
  • 一對一
    一對一關係可以用前面介紹的一對多關係表示,但呼叫 db.relationship() 時要把 uselist 設為 False ,把“多”變成“一”。

  • 多對多

tags = db.Table('tags',
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
    db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
)

class Page(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tags = db.relationship('Tag', secondary=tags,
        backref=db.backref('pages', lazy='dynamic'))

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)

資料庫操作

  • 建立表
python hello.py shell
>>> from hello import db
>>> db.create_all()
  • 刪除表
db.drop_all()
  • 插入行
#建立物件,模型的建構函式接受的引數是使用關鍵字引數指定的模型屬性初始值。
admin_role = Role(name='Admin')
user_role = Role(name='User')
user_susan = User(username='susan', role=user_role)#role 屬性也可使用,雖然它不是真正的資料庫列,但卻是一對多關係的高階表示。
user_john = User(username='john', role=admin_role)
#這些新建物件的 id 屬性並沒有明確設定,因為主鍵是由 Flask-SQLAlchemy 管理的。
print(admin_role.id)#None
#通過資料庫會話管理對資料庫所做的改動,在 Flask-SQLAlchemy 中,會話由 db.session 表示。
##首先,將物件新增到會話中
db.session.add(admin_role)
db.session.add(user_role)
db.session.add(user_susan)
db.session.add(user_john)
#簡寫:db.session.add_all([admin_role, user_role, user_john, user_susan])
##通過提交會話(事務),將物件寫入資料庫
db.session.commit()

會話提交

資料庫會話能保證資料庫的一致性。提交操作使用原子方式把會話中的物件全部寫入資料庫。如果在寫入會話的過程中發生了錯誤,整個會話都會失效。
資料庫會話也可 回滾 。呼叫 db.session.rollback() 後,新增到資料庫會話中的所有物件都會還原到它們在資料庫時的狀態。

  • 修改行
admin_role.name = 'Administrator'
db.session.add(admin_role)
session.commit()
  • 刪除行
db.session.delete(mod_role)
session.commit()
  • 查詢行

    • 查詢全部。Role.query.all()
    • 條件查詢(使用過濾器)。User.query.filter_by(role=user_role).all()
    user_role = Role.query.filter_by(name='User').first()#filter_by() 等過濾器在 query 物件上呼叫,返回一個更精確的 query 物件。

    常用過濾器

過濾器 說 明
filter() 把過濾器新增到原查詢上,返回一個新查詢
filter_by() 把等值過濾器新增到原查詢上,返回一個新查詢
limit() 使用指定的值限制原查詢返回的結果數量,返回一個新查詢
offset() 偏移原查詢返回的結果,返回一個新查詢
order_by() 根據指定條件對原查詢結果進行排序,返回一個新查詢
group_by() 根據指定條件對原查詢結果進行分組,返回一個新查詢

最常使用的SQLAlchemy查詢執行函式

方 法 說 明
all() 以列表形式返回查詢的所有結果
first() 返回查詢的第一個結果,如果沒有結果,則返回 None
first_or_404() 返回查詢的第一個結果,如果沒有結果,則終止請求,返回 404 錯誤響應
get() 返回指定主鍵對應的行,如果沒有對應的行,則返回 None
get_or_404() 返回指定主鍵對應的行,如果沒找到指定的主鍵,則終止請求,返回 404 錯誤響應
count() 返回查詢結果的數量
paginate() 返回一個 Paginate 物件,它包含指定範圍內的結果
  • 關係查詢

    
    #執行 user_role.users 表示式時,隱含的查詢會呼叫 all() 返回一個使用者列表。 query 物件是隱藏的,因此無法指定更精確的查詢過濾器。
    
    users = user_role.users
    
    #修改了關係的設定,加入了 lazy = 'dynamic' 引數,從而禁止自動執行查詢
    
    class Role(db.Model):
    users = db.relationship('User', backref='role', lazy='dynamic')
    
    #順序排列
    
    user_role.users.order_by(User.username).all()

在檢視函式中操作資料庫

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.name.data).first()
        if user is None:
            user = User(username = form.name.data)
            db.session.add(user)
            session['known'] = False
        else:
            session['known'] = True
        session['name'] = form.name.data
        form.name.data = ''
        return redirect(url_for('index'))
    return render_template('index.html', form = form, name = session.get('name'), known = session.get('known', False))

修改模板

{ % extends "base.html" % }
{ % import "bootstrap/wtf.html" as wtf % }
{ % block title % }Flasky{ % endblock % }
{ % block page_content % }
    <div class="page-header">
        <h1>Hello, { % if name % }{{ name }}{ % else % }Stranger{ % endif % }!</h1>
        { % if not known % }
            <p>Pleased to meet you!</p>
        { % else % }
            <p>Happy to see you again!</p>
        { % endif % }
    </div>
    {{ wtf.quick_form(form) }}
{ % endblock % }

整合 Python shell

讓 Flask-Script 的 shell 命令自動匯入特定的物件

from flask.ext.script import Shell
def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)  
manager.add_command("shell", Shell(make_context=make_shell_context))

make_shell_context() 函式註冊了程式、資料庫例項以及模型,因此這些物件能直接匯入 shell

使用 Flask-Migrate 實現資料庫遷移

建立遷移倉庫

pip install flask-migrate

配置

from flask.ext.migrate import Migrate, MigrateCommand
# ...
migrate = Migrate(app, db)
manager.add_command('db', MigrateCommand)

在維護資料庫遷移之前,要使用 init 子命令建立遷移倉庫

python hello.py db init

建立遷移指令碼

python hello.py db migrate -m "initial migration"

更新資料庫

python hello.py db upgrade

相關推薦

flask學習筆記(-資料庫)

Python 資料庫框架 大多數的資料庫引擎都有對應的 Python 包,包括開源包和商業包。Flask 並不限制你使用何種型別的資料庫包,因此可以根據自己的喜好選擇使用 MySQL、Postgres、SQLite、Redis、MongoDB 或者 Couch

Flask學習筆記之——藍圖、基於DBUtils實現資料庫連線池、上下文管理等

面向物件知識回顧 子類繼承父類的三種方式 class Dog(Animal): #子類 派生類 def __init__(self,name,breed, life_value,aggr): # Animal.__init__(self

flask學習筆記(十三) 資料庫補充

歡迎加入知了課堂,學習flask一、資料庫資料庫就是儲存資料的倉庫,其本質是一個檔案系統,資料按照特定的格式將資料儲存起來,使用者可以對資料庫中的資料進行增加,修改,刪除及查詢操作。通過資料庫管理系統對資料庫進行管理控制,這裡使用MySQL資料庫。MySQL中可以有多個數據庫

Flask學習筆記】數據模型設計

odi span ase doc href 評論 pre 和數 ont 【前言】對於像我一樣的新手來說,我覺得此環節難點主要是相關依賴包的安裝和Flask-SQLAlchemy的使用,下面將一一講解: 所謂數據模型,百度的解釋是:“數據模型(Data Mode

Flask 學習筆記

資源 第一條 log utf8 sel val time ESS 窗口 title: Flask筆記 環境安裝與搭建(Windows7 up) 1.python3.6或者2.7的安裝請參考百度資料 2.通過在cmd中鍵入下行命令安裝虛擬環境 pip install vir

學習筆記-資料庫增刪查

1.新增Insert Insert into 表名(列 1…列n) values(值1…值n) “INSERT INTO dept VALUES(1,‘人事’);” ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 這種方式,列的值必須和表的列的順序一直,不建議使用這種方式,如果後期表的順序變了

學習筆記-資料庫基本

所謂的建立表就是宣告列的過程,剩下的就是根據列區新增值 建庫:create database (庫名); 檢視:show databases; 刪除:dorp database (); decimal:精確度高於double>float char(0~255)定長字串,char(M

Flask學習筆記-PyCharm配置使用Flask-Script啟動以及開啟Debug模式

在PyCharm中安裝Flask-Script 在上一篇文章中介紹過的如何安裝Flask的外掛非常方便,點選“+”號檢索“flask-script”安裝即可。   程式碼中使用Flask-Script from flask.ext.script i

Shiro學習筆記——資料庫讀取許可權資訊(不使用硬編碼的方式)

在ShiroFilterFactoryBean初始化的過程中,會執行一個setFilterChainDefinitionMap方法,傳入了一個Map,該Map就是URL與許可權的對應關係。 編寫一個例

7.redis學習筆記-資料庫&RDB持久化.md

8. 資料庫 8.1. 介紹下這個資料庫 Redis伺服器將所有資料庫都儲存在伺服器狀態redis.h/redisServer結構的db陣列中,db陣列的每個項都是一個redis.h/redisDb結構,每個redisDb結構代表一個數據庫: struct r

Flask學習筆記(三)

繼承和block 1.繼承作用和語法 作用:可以把一些公共的程式碼放在父模板中, 避免每個模板寫到同樣的程式碼。 語法: #html {% extends 'base.html' %} # 2.block的實現: 作用:可以讓子模板實現一些自己的需求,父

Flask學習筆記(四)

進入虛擬環境 我的電腦的虛擬環境在F盤裡,命令列進入F盤後,直接打入Virtualenv\flask-env\Scripts\activate即可進入我的虛擬環境中使用flask。 退出虛擬環境:deactivate flask_sqlalchemy(連線資料庫

Flask學習筆記(一)

Flask學習筆記 —— 初識Flask 什麼是Flask (What is Flask) Flask 是一個基於Python語言的微型伺服器框架,其由 Armin Ronacher 於2010年4月1日提出。1 2其創始人 Armin Ronacher 為 F

Spring Security學習筆記-資料庫管理

Spring Security-資料庫管理   當一個使用者登陸時,會先執行身份認證,如果身份認證未通過則會要求使用者重新認證;當用戶身份認證通過後,則會呼叫角色管理器,判斷使用者是否可以訪問。這裡,如果要實現使用資料庫管理使用者及許可權,就需要自定義使用者登陸功能,而SpringSec

Flask學習筆記:建立一個簡單的Flask應用

1. 做好準備工作進入專案主目錄啟用虛擬環境2. 建立app包:在flask中,含有名為 __init__.py 檔案的子目錄被視為包,可以被匯入。在命令列輸入以下命令,建立一個名為app的目錄:(venv) $ mkdir app在app目錄中建立一個名為__init__.

flask學習筆記

flask 執行流程 creat一個app物件,通過Flask(name)來註冊方法,然後run_app 通過flask_script將app註冊到manager 可以自定義一些其他的command manager=Manager(app) 在cre

flask學習筆記(-模板)

為什麼使用模板 檢視函式的作用很明確,即生成請求的響應。但 Flask 檢視函式的兩個完全獨立的作用(處理邏輯和頁面)卻被融在一起。 例如,使用者在網站中註冊了一個新賬戶。使用者在表單中輸入電子郵件地址和密碼,然後點選提交按鈕。伺服器接收到包含使用者輸入資料

flask學習筆記(工廠函式)

        最近flask理解又進了一步,記錄一下。 關於工廠函式: bootstrap = Bootstrap() mail = Mail() moment = Moment() db = SQLAlchemy() pagedown = PageDown() log

Spring Security學習筆記資料庫驗證(四)

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframewo

資料庫系統概論第五版學習筆記資料庫完整性 第五章

一、基本內容 1. 定義:資料的正確性和相容性 2. 內容涉及    1)提供定義完整性約束條件的規則   ‚2)提供完整性檢查的方法    3)進行違約處理 3. 分類 實體完整性(對全碼約束)PRIMARY KEY        參照完整性(對外碼約束)REFERE