1. 程式人生 > >Flask——資料庫簡介

Flask——資料庫簡介

ORM

ORM:全拼 Object-Relation Mapping
中文名:物件關係對映
主要實現模型物件到關係資料庫資料的對映,比如把資料庫表每條記錄對映為一個模型物件。但是資料庫需要手動建立。
優點 :
只需要面向物件程式設計, 不需要面向資料庫編寫程式碼.
對資料庫的操作都轉化成對類屬性和方法的操作.
不用編寫各種資料庫的sql語句.
實現了資料模型與資料庫的解耦, 遮蔽了不同資料庫操作上的差異.
不在關注用的是mysql、oracle...等.
通過簡單的配置就可以輕鬆更換資料庫, 而不需要修改程式碼.
缺點 :
相比較直接使用SQL語句操作資料庫,有效能損失.
根據物件的操作轉換成SQL語句,根據查詢的結果轉化成物件, 在對映過程中有效能損失.
SQLAlchemy:關係型資料庫抽象框架,用來實現ORM
使用Flask-SQLAlchemy擴充套件包來具體實現SQLAlchemy。

Flask_SQLAlchemy的配置說明:

SQLALCEHMY_DATABASE_URI:用於連線資料庫URI
SQLALCHEMY_BINDS:一個對映binds到URI的字典
SQLALCHEMY_ECHO:如果設定為True,SQLAlchemy會列印mysql語句
SQLALCHEMY_RECORD_QUERIES:可以顯式的禁用或啟用查詢語句,查詢語句在調式或者測試模式自動啟用。
SQLALCEHMY_NATIVE_UNICODE:可以用於顯式禁用原生unicode支援,當使用不合適的指定無編碼的資料庫預設值時,這對於一些資料庫介面卡是必須的
SQLALCEHMY_POOL_SIZE:資料庫連線池的大小,預設是引擎的預設值,通常是5
SQLALCHEMY_POOL_TIMEOUT:設定連線池的連線超時時間,預設是10
SQLALCHEMY_POOL_RECYCLE:多少秒後自動收回連線,這對Mysql是必要的,它預設移除連線超過8小時的連線。注意如果使用了Mysql。Flask_SQLAlchemy自動設定這個值為2小時。

常用的SQLAlcehmy的欄位型別

Integer	:普通整數,一般是32位
SmallInteger:		取值範圍小的整數,一般是16位
BigInteger	:	不限制精度的整數
Float	:	浮點數
Numeric	:	普通整數,一般是32位
String	:變長字串
Text	:	變長字串,對較長或不限長度的字串做了優化
Unicode	:變長Unicode字串
UnicodeText	:	變長Unicode字串,對較長或不限長度的字串做了優化
Boolean	:	布林值
Date	:	時間
Time	:日期和時間
LargeBinary	:	二進位制檔案

常用的SQLAlcehmy列選項:

primary_key:	如果為True,代表表的主鍵
unique:	如果為True,代表這列不允許出現重複的值
index:如果為True,為這列建立索引,提高查詢效率
nullable:如果為True,允許有空值,如果為False,不允許有空值
default	:為這列定義預設值

常用的SQLAlcehmy的關係選項:

backref :在關係的另一模型中新增反向引用 
primary join: 明確指定兩個模型之間使用的聯結條件 
uselist: 如果為False,不使用列表,而使用標量值 
order_by: 指定關係中記錄的排序方式 
secondary: 指定多對多關係中關係表的名字 
secondary join :在SQLAlchemy中無法自行決定時,指定多對多關係中的二級聯結條件

程式碼

from flask import Flask
# 匯入擴充套件包
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 資料庫指定連線
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]/homework'
#動態追蹤修改,無論設定與否,不會影響程式碼的執行。只會提示警告資訊。如果設定為True,會跟蹤資料庫的變化,會影響程式碼的效率,設定為False,不影響程式碼的效率。
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
#展示sql語句:會轉換出mysql建立表操作的原理。
app.config['SQLALCHEMY_ECHO'] = True

# 使用sqlalchemy,需要例項化sqlalchemy,必需傳入例項app,讓策劃嗯需例項app和sqlalchemy進行關聯
db = SQLAlchemy(app)

"""
 需求:實現一對多模型類的定義和基本資料的增刪改查
 Role(角色)一方,管理員和普通使用者
 user(使用者)多方,具體的使用者
 實現流程:
 1.使用flask_sqlalchemy擴充套件包,配置資料庫的連線
 2.定義模型類
"""

# 定義模型類,必須繼承自db.Model
class Role(db.Model):
    # 資料庫表名,可以不定義,會預設建立同類型的表名,即role。
    # 表名的常見定義樣式:tb_roles;info_roles;
    __tablename__ = 'roles'
    #定義欄位
    id = db.Column(db.Integer,primary_key=True)
    info = db.Column(db.String(32),unique=True)
    # 一方定義關係:第一個引數表示另外一方的類名,第二個引數backref表示的是反向引用
    # role可以讓User物件使用,可以實現多對一的查詢,例如:一個人是管理員還是普通使用者?多對一查詢
    # us可以讓Role物件使用,實現一對多的查詢,例如:管理員有多少人?一對多查詢
    #關係引用在資料庫中沒有實體
    us = db.relationship('User',backref ='role')
    #定義__repr__方法:作用是返回一個物件的可讀字串
    def __repr__(self):
   		return  'info:%s' % self.info

    #定義使用者模型類:注意外來鍵(角色具體屬於的身份資訊)
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32))
    email = db.Column(db.String(32))
    pswd = db.Column(db.String(32))
    # 多方定義外來鍵,指向一方表名的主鍵id
    role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))
     #定義__repr__方法:
    def __repr__(self):
   		return  'name:%s' % self.name

 	
@app.route('/')
def index():
    return 'hello world'
	# db.session.rollback() 回滾
"""
Role.query.get(2) get查詢接收的引數為主鍵,如果不存在,返回空

>>> User.query.filter() 返回的基礎的查詢物件
<flask_sqlalchemy.BaseQuery object at 0x10958fb00>

filter和filter_by查詢:都是查詢過濾器,要使用查詢執行器;
User.query.filter(User.name=='wang').all() 引數:必須使用類名.欄位,可以使用運算子>= == <= !=
使用filter居多,因為可以有更多的過濾。
補充:在使用或過濾的時候,需要from sqlalcehmy import or_  先導,不能直接使用。
User.query.filter_by(name='wang').all()引數:只需要使用欄位名,不能使用運算子。

查詢排序:
>>> User.query.filter().order_by(User.id.desc()).all() desc()表示降序排序
[name:zhou, name:chen, name:zhang, name:wang]
>>> User.query.filter().order_by(User.id.asc()).all() asc()表示升序排序
[name:wang, name:zhang, name:chen, name:zhou]

分頁:第一個引數表示頁數,第二個引數表示每頁條目數,第三個引數分頁異常不報錯
>>> pa = User.query.filter().paginate(1,2,False)
>>> pa.items # 獲取分頁後的資料
[name:wang, name:zhang]
>>> pa.pages # 獲取分頁後的總頁數
2
>>> pa.page # 獲取當前頁數
1
>>> pa = User.query.filter().paginate(2,2,False)
>>> pa.items
[name:chen, name:zhou]
>>> pa.pages
2
>>> pa.page
2

"""
if __name__ == '__main__':
    # 刪除表
    db.drop_all()
    # 建立表
    db.create_all()
    #新增測試資料
    ro1 = Role(info='admin')
    ro2 = Role(info='user')
    # session表示資料庫會話物件,add_all表示新增多條資料/add()
    # commit表示提交資料到資料庫
    db.session.add_all([ro1, ro2])
    db.session.commit()
    us1 = User(name='wang', email='[email protected]', pswd='123456', role_id=ro1.id)
    us2 = User(name='zhang', email='[email protected]', pswd='201512', role_id=ro2.id)
    us3 = User(name='chen', email='[email protected]', pswd='987654', role_id=ro2.id)
    us4 = User(name='zhou', email='[email protected]', pswd='456789', role_id=ro1.id)
    db.session.add_all([us1, us2, us3, us4])
    db.session.commit()
	app.run(debug=True)

常用SQLAlchemy查詢資料庫:

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物件,它包含指定範圍內的結果

資料庫的查詢操作:

first()返回查詢到的第一個物件
all()返回查詢到的所有物件
filter_by()精準查詢
filter()模糊查詢
get()引數為主鍵,如果主鍵不存在沒有返回內容
not_相當於取反,但是and_,or_xu需要匯入
查詢資料後刪除:需要先給查詢後一個變數儲存,然後db.session.delete(變數名),注意需要提交。
更新資料:和刪除資料類似,然後修改提交。
關聯查詢:
查詢角色的所有使用者
**#查詢roles表id為1的角色
ro1 = Role.query.get(1)
#查詢該角色的所有使用者
ro1.us.all()**
**查詢使用者所屬角色
#查詢users表id為3的使用者
us1 = User.query.get(3)
#查詢使用者屬於什麼角色
us1.role**