sqlalchemy是一個操作關系型數據庫的ORM工具。下面研究一下單獨使用和其在flask框架中的使用方法。
直接使用sqlalchemy操作數據庫
安裝sqlalchemy
pip install sqlalchemy
初始化及操作數據庫
# 導入:
from sqlalchemy import Column, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# 創建對象的基類:
Base = declarative_base()
class User(Base):
'''用戶信息表'''
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(80), unique=True)
email = Column(String(320), unique=True)
password = Column(String(32), nullable=False)
user = User(username='ming', email='dddd', password='1234567')
# 初始化數據庫連接:
engine = create_engine('mysql+mysqlconnector://root:password@localhost:3306/test')
# 創建DBSession類型:
DBSession = sessionmaker(bind=engine)
# 創建單個會話
session = DBSession()
session = db_session()
session.add(user)
session.commit()
session.close()
# 通過創建會話池連接
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
session = db_session()
session.add(user)
session.commit()
session.close()
# 也可以創建連接
con = engine.connect()
con.execute("一個表對象",name='ffff',email='dddd', password='1234567')
con.close()
在flask框架中集成使用
安裝
pip install Flask-SQLAlchemy
- 如果需要操作mysql數據庫,還需要安裝pymysql;
pip install pymysql
配置文件
- Flask-SQLAlchemy可以將關於SQLAlchemy的配置集成到flask的配置文件中去,在初始化app的時候一起加載。相關的配置鍵有:
SQLALCHEMY_DATABASE_URI
用於連接數據的數據庫。例如:
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://caiwp:mysql@192.168.1.23:3307/tms_mysql?charset=utf8'
其格式為:mysql://username:password@server/db?編碼
注意默認使用mysqldb連接數據庫,要使用pymysql就需要用mysql+pymysql的格式;
SQLALCHEMY_COMMIT_ON_TEARDOWN
設置是否在每次連接結束后自動提交數據庫中的變動。
example:
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
SQLALCHEMY_BINDS
一個映射綁定 (bind) 鍵到 SQLAlchemy 連接 URIs 的字典。他可以用來連接多個數據庫。
example:
SQLALCHEMY_BINDS = {
'users': 'mysqldb://localhost/users',
'appmeta': 'sqlite:////path/to/appmeta.db'
}
# 上面除了默認的連接外,又連接了兩個數據庫,分別命名users,appmeta。在創建模型的時候可以為相應的操作定制化;
# 更多的詳細參考:http://www.pythondoc.com/flask-sqlalchemy/binds.html#binds
SQLALCHEMY_ECHO
如果設置成 True,SQLAlchemy 將會記錄所有發到標准輸出(stderr)的語句,這對調試很有幫助;默認為false;
如:
SQLALCHEMY_ECHO = True
SQLALCHEMY_RECORD_QUERIES
可以用於顯式地禁用或者啟用查詢記錄。查詢記錄 在調試或者測試模式下自動啟用。
一般我們不設置。
SQLALCHEMY_NATIVE_UNICODE
可以用於顯式地禁用支持原生的unicode。
SQLALCHEMY_POOL_SIZE
數據庫連接池的大小。默認是數據庫引擎的默認值 (通常是 5)。
如:
SQLALCHEMY_POOL_SIZE = 10
SQLALCHEMY_TRACK_MODIFICATIONS
如果設置成 True (默認情況),Flask-SQLAlchemy 將會追蹤對象的修改並且發送信號。這需要額外的內存,如果不必要的可以禁用它。
example:
SQLALCHEMY_TRACK_MODIFICATIONS = Flase
SQLALCHEMY_MAX_OVERFLOW
控制在連接池達到最大值后可以創建的連接數。當這些額外的連接使用后回收到連接池后將會被斷開和拋棄。保證連接池只有設置的大小;
如:
SQLALCHEMY_MAX_OVERFLOW = 5
SQLALCHEMY_POOL_TIMEOUT
指定數據庫連接池的超時時間。默認是 10。
example:
SQLALCHEMY_POOL_TIMEOUT = 10
SQLALCHEMY_POOL_RECYCLE
自動回收連接的秒數。這對MySQL是必須的,默認情況下MySQL會自動移除閑置8小時或者以上的連接,Flask-SQLAlchemy會自動地設置這個值為 2 小時。也就是說如果連接池中有連接2個小時被閑置,那么其會被斷開和拋棄;
手動設置:
SQLALCHEMY_POOL_RECYCLE = 1200
常用配置
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://caiwp:mysql@192.168.1.23:3307/tms_mysql?charset=utf8'
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
# 下面兩項調試階段啟動,部署時關閉
SQLALCHEMY_TRACK_MODIFICATIONS = True
SQLALCHEMY_ECHO = True
常用的字段、關系類型
- 常用的字段
類型名 python類型 說明
Integer int 普通整數,一般是32位
SmallInteger int 取值范圍小的整數,一般是16位
BigInteger int或long 不限制精度的整數
Float float 浮點數
Numeric decimal.Decimal 普通整數,一般是32位
String str 變長字符串
Text str 變長字符串,對較長或不限長度的字符串做了優化
Unicode unicode 變長Unicode字符串
UnicodeText unicode 變長Unicode字符串,對較長或不限長度的字符串做了優化
Boolean bool 布爾值
Date datetime.date 時間
Time datetime.datetime 日期和時間
LargeBinary str 二進制文件
Enum enum 枚舉類型
- 常用列選項
primary_key 如果為True,代表表的主鍵
unique 如果為True,代表這列不允許出現重復的值
index 如果為True,為這列創建索引,提高查詢效率
nullable 如果為True,允許有空值,如果為False,不允許有空值
default 為這列定義默認值,如default=1
- 常用的關系選項
backref 在關系的另一模型中添加反向引用,用於找到父表
primary join 明確指定兩個模型之間使用的聯結條件
uselist 如果為False,不使用列表,而使用標量值
order_by 指定關系中記錄的排序方式
secondary 指定多對多中記錄的排序方式
secondary join 在SQLAlchemy中無法自行決定時,指定多對多關系中的二級聯結條件
創建模型類
from flask.ext.sqlalchemy import SQLAlchemy
# 指定一個字段為外鍵,必須使用類
from sqlalchemy.schema import ForeignKey
# 創建一個db對象
db = SQLAlchemy()
class User(db.Model):
__bind_key__ = 'xxx' # 可以指定為哪個數據庫定義表
__tablename__ = 'users' # 定義表的名字
# 定義表中的列字段,接收所有相關的對字段的定義的信息
id = db.Column(db.Integer, primary_key=True) # 如果第一個參數是一個字符串,那么使用該字符串作為字段名
username = db.Column(db.String(80), unique=True)
# 定義相關聯的表,backref為Address賦予了一個新的屬性,讓Address可以通過address.person找到user表
addresses = db.relationship('Address', backref='person',
lazy='dynamic')
# 可以手動初始化,也可以不做,那么會自動使用字段的變量名作為字段名
def __init__(self, username, email):
self.username = username
self.email = email
# 輸出字符串
def __repr__(self):
return '<User %r>' % self.username
class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(50))
# 指定外鍵
person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
#也可以直接創建表,一般用於多對多關系
tags = db.Table('uesrs',
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
)
引入上下文
SQLAlchemy是一個全局對象,如果有多個應用程序的話,必須要讓SQLAlchemy對象知道當前服務於哪個app。
# 如果只有一個app,可以創建時初始化
app = Flask(__name__)
db = SQLAlchemy(app)
# 如果有多個應用
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
# 這個函數其讀取app的配置參數,將和數據庫相關的配置加載到SQLAlchemy對象中
db.init_app(app)
return app
數據庫的操作
- 創建和刪除表
# 刪除所有的表,bind參數可以指定為哪一個數據庫創建表,默認為__all__,所有的數據庫;
# app傳入是為了獲取初始化的相關參數,如果db已經初始化,則不需要傳入
db.drop_all(bind="",app=app)
# 創建所有的表,其參數和drop_all是一樣的
db.create_all()
- 數據的增刪改查
# 首先創建一個實例
user = User(username='aaa')
# 插入一條數據,這時會發出一條insert語句,但是該事務還沒有提交,可以放棄
# 每個add操作都是一個數據
db.session.add(user)
# 批量添加數據
db.session.add_all([user1,user2])
# 刪除數據
db.session.delete(user1)
# 提交給數據庫
db.session.commit()
# 更新數據
User.query.filter_by(name='xxx').update({'name':'li'})
# 查詢query屬性
User.query.filter().all()
- 過濾器的使用
# 常用的過濾器
filter() 把過濾器添加到原查詢上,返回一個新查詢
filter_by() 把等值過濾器添加到原查詢上,返回一個新查詢
limit() 使用指定的值限定原查詢返回的結果
offset() 偏移原查詢返回的結果,返回一個新查詢
order_by() 根據指定條件對原查詢結果進行排序,返回一個新查詢
group_by() 根據指定條件對原查詢結果進行分組,返回一個新查詢
# 精確查詢
person = User.query.filter_by(name='aaa',id='23').all()
# 模糊查詢,
persons = User.query.filter(User.name.endswith('g')).all()
User.query.filter(User.id>3).all()
# 按username排序
User.query.order_by(User.username)
# 限制返回3個數據
User.query.limit(3).all()
# 條件查詢
# 邏輯非
User.query.filter(User.name!='xxx').all()
# 邏輯與
from sqlalchemy import and_
User.query.filter(and_(User.name!='xxx',User.address.endwith('g')).all()
# 邏輯或
User.query.filter(or_(User.name!='xxx',User.address.endwith('g'))).all()
# 取反,名字不是xxx的所有
User.query.filter(not_(User.name=='xxx')).all()
- 執行器的使用
all() 以列表形式返回查詢的所有結果
first() 返回查詢的第一個結果,如果未查到,返回None
first_or_404() 返回查詢的第一個結果,如果未查到,返回404
get() 返回指定主鍵對應的行,如不存在,返回None
get_or_404() 返回指定主鍵對應的行,如不存在,返回404
count() 返回查詢結果的數量
paginate() 返回一個Paginate對象,它包含指定范圍內的結果
# 使用主鍵查詢,id = 1
User.query.get(1)
數據庫的遷移
-
我們可以使用create_all()函數來創建數據庫的表,不過在flask中有更加完善的管理工具flask-migrate;
-
安裝
pip install flask-migrate
- 實例
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate,MigrateCommand
from flask_script import Shell,Manager
app = Flask(__name__)
manager = Manager(app)
db = SQLAlchemy(app)
#第一個參數是Flask的實例,第二個參數是Sqlalchemy數據庫實例
migrate = Migrate(app,db)
#manager是Flask-Script的實例,這條語句在flask-Script中添加一個db命令
manager.add_command('db',MigrateCommand)
# 生成相關的遷移文件,創建migrations文件夾,這個文件在項目的目錄下
python manage.py db init
# 生成遷移腳本,生成upgrade()和downgrade()函數的內容,這是將要執行的操作;
python manage.py db migrate -m '修改說明'
#更新數據庫
python manage.py db upgrade
# 如果需要歷史版本,回退
python manage.py db history # 先查詢歷史版本
# 執行回退
python manage.py db downgrade 版本號