flask學習筆記(-資料庫)
Python 資料庫框架
大多數的資料庫引擎都有對應的 Python 包,包括開源包和商業包。Flask 並不限制你使用何種型別的資料庫包,因此可以根據自己的喜好選擇使用 MySQL、Postgres、SQLite、Redis、MongoDB 或者 CouchDB。
如果這些都無法滿足需求,還有一些資料庫抽象層程式碼包供選擇,例如SQLAlchemy和MongoEngine。你可以使用這些抽象包直接處理高等級的 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] |
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