Flask本身不限定數(shù)據(jù)庫的選擇,你可以選擇SQL或NOSQL的任何一種。也可以選擇更方便的SQLALchemy,類似于Django的ORM。SQLALchemy實際上是對數(shù)據(jù)庫的抽象,讓開發(fā)者不用直接和SQL語句打交道,而是通過Python對象來操作數(shù)據(jù)庫,在舍棄一些性能開銷的同時,換來的是開發(fā)效率的較大提升。
SQLAlchemy是一個關(guān)系型數(shù)據(jù)庫框架,它提供了高層的ORM和底層的原生數(shù)據(jù)庫的操作。flask-sqlalchemy是一個簡化了SQLAlchemy操作的flask擴展。
安裝Flask-SQLALchemy
pip install flask-sqlalchemy
#同時需要安裝數(shù)據(jù)庫驅(qū)動層(有的人肯定很迷茫他們的關(guān)系,其實就是下面這樣,我這里選擇mysql官方推薦的mysql-python)
1、pymysql支持python3、python2
2、mysql-python支持python2
3、flask-mysqladb是在mysql-python(mysqpl官方提供的驅(qū)動包)基礎(chǔ)上進行的封裝
pip install mysql-python
常用的SQLAlchemy字段類型
| 類型名 | python中類型 | 說明 |
|---|---|---|
| Integer | int | 普通整數(shù),一般是32位 |
| SmallInteger | int | 取值范圍小的整數(shù),一般是16位 |
| BigInteger | int或long | 不限制精度的整數(shù) |
| Float | float | 浮點數(shù) |
| Numeric | decimal.Decimal | 普通整數(shù),一般是32位 |
| String | str | 變長字符串 |
| Text | str | 變長字符串,對較長或不限長度的字符串做了優(yōu)化 |
| Unicode | unicode | 變長Unicode字符串 |
| UnicodeText | unicode | 變長Unicode字符串,對較長或不限長度的字符串做了優(yōu)化 |
| Boolean | bool | 布爾值 |
| Date | datetime.date | 時間 |
| Time | datetime.datetime | 日期和時間 |
| LargeBinary | str | 二進制文件 |
代碼實例
# coding:utf-8
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#配置數(shù)據(jù)庫連接的對象
class Config(object):
"""配置參數(shù)"""
# sqlalchemy的配置參數(shù) 帳號:密碼 地址 端口 數(shù)據(jù)庫
SQLALCHEMY_DATABASE_URI = "mysql://root:mysql@127.0.0.1:3306/db_test"
# 設(shè)置sqlalchemy自動更跟蹤數(shù)據(jù)庫(數(shù)據(jù)庫表手動更新是同步跟新到對象)
SQLALCHEMY_TRACK_MODIFICATIONS = True
#查詢時會顯示原始SQL語句
SQLALCHEMY_ECHO = True
#加載數(shù)據(jù)庫配置對象
app.config.from_object(Config)
# 創(chuàng)建數(shù)據(jù)庫sqlalchemy工具對象
db = SQLAlchemy(app)
class Role(db.Model):
"""用戶角色/身份表"""
#重命名表名
__tablename__ = "tbl_roles"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32), unique=True)
#這個重點介紹一下,這是額外添加的一個屬性,并不會添加在表里面
users = db.relationship("User", backref="role")
def __repr__(self):
"""定義之后,可以讓顯示對象的時候更直觀"""
return "Role object: name=%s" % self.name
# 表名的常見規(guī)范
# ihome -> ih_user 數(shù)據(jù)庫名縮寫_表名
# tbl_user tbl_表名
# 創(chuàng)建數(shù)據(jù)庫模型類
class User(db.Model):
"""用戶表"""
__tablename__ = "tbl_users" # 指明數(shù)據(jù)庫的表名
id = db.Column(db.Integer, primary_key=True) # 整型的主鍵,會默認設(shè)置為自增主鍵
name = db.Column(db.String(64), unique=True)
email = db.Column(db.String(128), unique=True)
password = db.Column(db.String(128))
# 添加外鍵 關(guān)聯(lián)角色表的id
role_id = db.Column(db.Integer, db.ForeignKey("tbl_roles.id"))
def __repr__(self):
return "User object: name=%s" % self.name
if __name__ == '__main__':
# 清除數(shù)據(jù)庫里的所有數(shù)據(jù)
db.drop_all()
# 創(chuàng)建所有的表
db.create_all()
# 創(chuàng)建對象
role1 = Role(name="admin")
# session記錄對象任務(wù)
db.session.add(role1)
# 提交任務(wù)到數(shù)據(jù)庫中
db.session.commit()
role2 = Role(name="stuff")
db.session.add(role2)
db.session.commit()
us1 = User(name='wang', email='wang@163.com', password='123456', role_id=role1.id)
us2 = User(name='zhang', email='zhang@189.com', password='201512', role_id=role2.id)
us3 = User(name='chen', email='chen@126.com', password='987654', role_id=role2.id)
us4 = User(name='zhou', email='zhou@163.com', password='456789', role_id=role1.id)
# 一次保存多條數(shù)據(jù)
db.session.add_all([us1, us2, us3, us4])
db.session.commit()
常用的SQLAlchemy查詢過濾器
| 過濾器 | 說明 |
|---|---|
| filter() | 把過濾器添加到原查詢上,返回一個新查詢 |
| filter_by() | 把等值過濾器添加到原查詢上,返回一個新查詢 |
| limit | 使用指定的值限定原查詢返回的結(jié)果 |
| offset() | 偏移原查詢返回的結(jié)果,返回一個新查詢 |
| order_by() | 根據(jù)指定條件對原查詢結(jié)果進行排序,返回一個新查詢 |
| group_by() | 根據(jù)指定條件對原查詢結(jié)果進行分組,返回一個新查詢 |
常用的SQLAlchemy查詢執(zhí)行器
| 方法 | 說明 |
|---|---|
| all() | 以列表形式返回查詢的所有結(jié)果 |
| first() | 返回查詢的第一個結(jié)果,如果未查到,返回None |
| first_or_404() | 返回查詢的第一個結(jié)果,如果未查到,返回404 |
| get() | 返回指定主鍵對應(yīng)的行,如不存在,返回None |
| get_or_404() | 返回指定主鍵對應(yīng)的行,如不存在,返回404 |
| count() | 返回查詢結(jié)果的數(shù)量 |
| paginate() | 返回一個Paginate對象,它包含指定范圍內(nèi)的結(jié)果 |
插入一條數(shù)據(jù)
ro = Role(name='admin')
db.session.add(ro)
db.session.commit()
查詢:filter_by精確查詢
User.query.filter_by(name='wang').all()
first()返回查詢到的第一個對象
User.query.first()
all()返回查詢到的所有對象
User.query.all()
filter模糊查詢,返回名字結(jié)尾字符為g的所有數(shù)據(jù)。
User.query.filter(User.name.endswith('g')).all()
get(),參數(shù)為主鍵,如果主鍵不存在沒有返回內(nèi)容
User.query.get()
邏輯非,返回名字不等于wang的所有數(shù)據(jù)。
User.query.filter(User.name!='wang').all()
邏輯與,需要導(dǎo)入and,返回and()條件滿足的所有數(shù)據(jù)。
from sqlalchemy import and_
User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()
邏輯或,需要導(dǎo)入or_
from sqlalchemy import or_
User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()
not_ 相當(dāng)于取反
from sqlalchemy import not_
User.query.filter(not_(User.name=='chen')).all()
查詢數(shù)據(jù)后刪除
user = User.query.first()
db.session.delete(user)
db.session.commit()
User.query.all()
更新數(shù)據(jù)
user = User.query.first()
user.name = 'wang'
db.session.commit()
User.query.first()
使用update
User.query.filter_by(name='zhang').update({'name':'li'})
關(guān)聯(lián)查詢示例:角色和用戶的關(guān)系是一對多的關(guān)系,一個角色可以有多個用戶,一個用戶只能屬于一個角色。
查詢角色的所有用戶:查詢roles表id為1的角色
ro1 = Role.query.get(1)
#查詢該角色的所有用戶
ro1.us
查詢用戶所屬角色:
#查詢users表id為2的用戶
us1 = User.query.get(2)
#查詢用戶屬于什么角色
us1.role