最常用的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
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 = http://blog.csdn.net/sun_dragon/article/details/''
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