1 定義模型python
在 ORM 中,模型通常是一個 Python 類, 表明數據庫中的一張表, 類中的屬性對應數據庫表中的列。Flask-SQLAlchemy 建立的數據庫實例爲模型提供了一個基類db.Model以及一系列輔助類和輔助函數,可用於定義 模型/表 的結構。下面的例子定義了兩個表,一個是用戶角色,一個是用戶信息sql
db.Column 類構造函數的第一個參數是class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) 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數據庫表列/模型屬性 的類型
db.Column 中其他的參數指定屬性的配置選項
。shell
選項名 | 說 明 |
---|---|
primary_key | 若是設爲 True,這列就是表的主鍵 |
unique | 若是設爲 True,這列不容許出現重複的值 |
index | 若是設爲 True,爲這列建立索引,提高查詢效率 |
nullable | 若是設爲 True,這列容許使用空值;若是設爲 False,這列不容許使用空值 |
default | 爲這列定義默認值數據庫 |
2 數據庫操做ruby
2.1 建立表session
SQLAlchemy 的實現,能夠看到 Model 是一個元類,在繼承這個類來聲明子類的時候,會把表模型註冊到 sqlalchemy 裏,因此在 create_all 以前必須把模型的聲明導入進來, 好比你可能須要這樣作from model.account import User,User的定義是def User(db.Model)這樣的,好比app
查看程序目錄,會發現新建了一個名爲app.db的文件。這個 SQLite 數據庫文件 的名字就是在配置中指定的。若是數據庫表已經存在於數據庫中,那麼 db.create_all() 不會從新建立或者更新這個表
更新現有數據庫表的粗暴方式是先再從新建立:(venv) $ python hello.py shell # 進入 Python shell >>> from hello import db # 從`hello.py`導入建立的數據庫實例 >>> db.create_all()刪除舊錶
這個方法有個咱們不想看到的反作用,它把數據庫中了。末尾將會介紹一種稱爲的方式用於更新數據庫
>>> db.drop_all() >>> db.create_all()原有的數據都銷燬數據庫遷移
2.1 插入記錄函數
>>> from hello import Role, User >>> admin_role = Role(name='Admin') >>> mod_role = Role(name='Moderator') >>> user_role = Role(name='User') >>> user_john = User(username='john', role=admin_role) >>> user_susan = User(username='susan', role=user_role) >>> user_david = User(username='david', role=user_role)
模型的構造函數接受的參數是使用關鍵字參數指定的模型屬性初始值。注意,role 屬性也可以使用,雖然它不是真正的數據庫列,但倒是一對多關係的高級表示。這些新建對象的 id 屬性並無明確設定,由於主鍵是由 Flask-SQLAlchemy 管理的。如今這些對象只存在於 Python 中,還未寫入數據庫。所以id 還沒有賦值spa
經過數據庫會話管理對數據庫所作的改動,在 Flask-SQLAlchemy 中,會話由 db.session 表示。準備把對象寫入數據庫以前,先要將其添加到會話中code
或者簡寫成:>>> db.session.add(admin_role) >>> db.session.add(mod_role) >>> db.session.add(user_role) >>> db.session.add(user_john) >>> db.session.add(user_susan) >>> db.session.add(user_david)
爲了,咱們要:>>> db.session.add_all([admin_role, mod_role, user_role, ... user_john, user_susan, user_david])把對象寫入數據庫調用 commit() 方法提交會話
>>> db.session.commit()
2.1 修改記錄
下面這個例子把 "Admin" 角色重命名爲 "Administrator":
>>> admin_role.name = 'Administrator' >>> db.session.add(admin_role) >>> db.session.commit()
2.1 刪除記錄
數據庫會話還有個 delete() 方法。下面這個例子把 "Moderator" 角色從數據庫中刪除
>>> db.session.delete(mod_role) >>> db.session.commit()
2.1 查詢記錄
Flask-SQLAlchemy 爲每一個模型類都提供了 query 對象。最基本的模型查詢是取回對應表中的全部記錄:
使用過濾器能夠配置 query 對象進行更精確的數據庫查詢。下面這個例子查找角色爲 "User" 的全部用戶:>>> Role.query.all() [<Role u'Administrator'>, <Role u'User'>] >>> User.query.all() [<User u'john'>, <User u'susan'>, <User u'david'>]
若要查看 SQLAlchemy 爲查詢生成的原生 SQL 查詢語句,只需把 query 對象轉換成字符串 :>>> User.query.filter_by(role=user_role).all() # user_role = Role(name='User'), role=user_role [<User u'susan'>, <User u'david'>]
若是你退出了 shell 會話,前面這些例子中建立的對象就不會以 Python 對象的形式存在,而是做爲各自數據庫表中的行。若是你打開了一個新的 shell 會話,就要從數據庫中讀取行, 再從新建立 Python 對象。下面這個例子發起了一個查詢,加載名爲 "User" 的用戶角色:>>> str(User.query.filter_by(role=user_role)) 'SELECT users.id AS users_id, users.username AS users_username, users.role_id AS users_role_id FROM users WHERE :param_1 = users.role_id'
可在 query 對象上調用的經常使用過濾器
>>> user_role = Role.query.filter_by(name='User').first()
過濾器 | 說明 |
---|---|
filter() | 把過濾器添加到原查詢上,返回一個新查詢 |
filter_by() | 把等值過濾器添加到原查詢上,返回一個新查詢 |
limit() | 使用指定的值限制原查詢返回的結果數量,返回一個新查詢 |
offset() | 偏移原查詢返回的結果,返回一個新查詢 |
order_by() | 根據指定條件對原查詢結果進行排序,返回一個新查詢 |
group_by() | 根據指定條件對原查詢結果進行分組,返回一個新查詢 |
在查詢上應用指定的過濾器後
,經過調用 all() 執行查詢,以列表的形式返回結果。除了 all() 以外,還有其餘方法能觸發查詢執行
。
經常使用查詢執行函數
方法 | 說明 |
---|---|
all() | 以列表形式返回查詢的全部結果 |
first() | 返回查詢的第一個結果,若是沒有結果,則返回 None |
first_or_404() | 返回查詢的第一個結果,若是沒有結果,則終止請求,返回 404 錯誤響應 |
get() | 返回指定主鍵對應的行,若是沒有對應的行,則返回 None |
get_or_404() | 返回指定主鍵對應的行,若是沒找到指定的主鍵,則終止請求,返回 404 錯誤響應 |
count() | 返回查詢結果的數量 |
paginate() | 返回一個 Paginate 對象,它包含指定範圍內的結果 |
下面這個例子分別從關係的兩端查詢角色和用戶之間的一對 多關係:
>>> users = user_role.users
>>> users
[<User u'susan'>, <User u'david'>] >>> users[0].role <Role u'User'>
這個例子中的 user_role.users 查詢有個小問題。執行 user_role.users 表達式時,隱含的查詢會調用 all() 返回一個用戶列表。query 對象是隱藏的,所以沒法指定更精確的查詢 過濾器。就這個特定示例而言,返回一個按照字母順序排序的用戶列表可能更好。
在示例 5-4中,咱們修改了關係的設置,加入了lazy = 'dynamic'參數,從而禁止自動執行查詢。
class Role(db.Model): # ... users = db.relationship('User', backref='role', lazy='dynamic') # ...
這樣配置關係以後,user_role.users 會返回一個還沒有執行的查詢,所以能夠在其上添加過 濾器:
>>> user_role.users.order_by(User.username).all()
[<User u'david'>, <User u'susan'>] >>> user_role.users.count() 2