使用flask開發RESTful架構的api伺服器端(4)–flask操作資料庫
flask有一個對資料庫的擴充套件flask-sqlalchemy,它簡化了在flask中對sqlalchemy的操作,sqlalchemy是一個強大的關係資料庫框架,支援一些資料庫後端,提供高階的ORM和底層訪問資料庫的本地sql功能;
使用pip來安裝flask-sqlalchemy
1 | pip install flask-sqlalchemy |
在flask-sqlalchemy中,sql被指定為URL,訪問mysql的url如下:
1 | mysql://username:[email protected]/database |
在URL中hostname是指託管mysql服務的伺服器,可以使localhost也可以是遠端伺服器,資料庫伺服器可以託管多個數據庫,所以database要指定連線的資料庫名,username和password是資料庫的身份驗證;
應用程式資料庫URL必須在flask配置物件中的SQLALCHEMY_DATABASE_URI中進行配置,另一個有用的選項是SQLALCHEMY_COMMIT_ON_TEARDOWN,可以設定為True來啟動自動提交資料庫更改在每個請求中:
1234567891011 | from flask import Flaskfrom flask.ext.sqlalchemy import SQLAlchemyimport configdatabaseurl='mysql://%s:%[email protected]%s:%s/%s'%(config.MYSQL_USER,config.MYSQL_PASS,config.MYSQL_HOST,config.MYSQL_PORT,config.MYSQL_DB)app=Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI']=databaseurlapp.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=Truedb=SQLAlchemy(app) |
由SQLAlchemy例項化的db物件表示資料庫且提供訪問flask-sqlalchemy的所有功能;
flask_sqlalchemy使用模型來定義資料庫表,一個模型通常是一個帶有屬性的python類,其屬性與資料庫表的列相匹配對應,flask-sqlalchemy資料庫例項提供了一個基類以及一組輔助類和函式用於定義它的結構,如下定義了一個student模型:
1234567891011121314 | classstudent(db.Model):__tablename__='student'id=db.Column(db.Integer,primary_key=True,nullable=False)name=db.Column(db.String(20),nullable=False)age=db.Column(db.Integer,nullable=False)def __init__(self,id,name,age):self.id=idself.name=nameself.age=agedef __repr__(self):return''%(self.id,self.name) |
__tablename__類變數定義資料庫中表的名稱,如果預設,flask_sqlalchemy會指定預設表名,其餘的變數是模型的屬性,定義為db.Column類的例項;
傳給db.Column建構函式的第一個引數是資料庫列的型別也就是模型屬性的資料型別:
型別名稱 | python型別 | 描述 |
Integer | int | 常規整型,通常為32位 |
SmallInteger | int | 短整型,通常為16位 |
BigInteger | int或long | 精度不受限整型 |
Float | float | 浮點型 |
Numeric | decimal | 定點數 |
String | str | 可變長度字串 |
Text | str | 可變長度字串,適合大量文字 |
Unicode | unicode | 可變長度Unicode字串 |
Boolean | bool | 布林值 |
Date | datetime.date | 日期型別 |
Time | datetime.time | 時間型別 |
Daetime | datetime.datetime | 日期時間型別 |
Interval | datetime.timedate | 時間間隔 |
Enum | str | 字元列表 |
PickleType | 任意Python物件 | 自動Pickle序列化 |
LargeBinary | str | 二進位制 |
其它的引數為每個屬性指定了配置選項:
可選引數 | 描述 |
primary_key | 設定為True,該列為表的主鍵 |
unique | 設定為True,該列不允許相同的值 |
index | 設定為True,為該列建立索引 |
nullable | 設定為True,允許為空 |
default | 定義該列的預設值 |
一個簡單的例子,使用POST插入學生資訊,使用GET來獲取資訊:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 | from flask import Flaskfrom flask import requestfrom flask import jsonifyfrom flask.ext.sqlalchemy import SQLAlchemyimport configdatabaseurl='mysql://%s:%[email protected]%s:%s/%s'%(config.MYSQL_USER,config.MYSQL_PASS,config.MYSQL_HOST,config.MYSQL_PORT,config.MYSQL_DB)app=Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI']=databaseurlapp.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=Truedb=SQLAlchemy(app)classmytable(db.Model):id=db.Column(db.Integer,primary_key=True,nullable=False)name=db.Column(db.String(20),nullable=False)age=db.Column(db.Integer,nullable=False)def __init__(self,id,name,age):self.id=idself.name=nameself.age=agedef __repr__(self):return''%(self.id,self.name)db.create_all()@app.route('/',methods=['POST'])def hello():ifnotrequest.json:return"failed!",400student={'id':request.json['id'],'name':request.json['name'],'age':request.json['age']}#初始化student物件stu=mytable(int(student['id']),student['name'],int(student['age']))#將新增專案插入資料庫db.session.add(stu)#提交修改db.session.commit()return"Hello World!"@app.route('/',methods=['GET'])def get_one():ifnotrequest.args['id']:abort(400)get_id=request.args['id']#得到表中所有的資料ids=mytable.query.all()#使用filter找到指定專案get=mytable.query.filter_by(id=get_id).first()#獲取表成員屬性ret='id=%d,name=%s,age=%d'%(get.id,get.name,get.age)returnretapp.run(debug=True) |
使用post上傳資訊後,資料或同步儲存到資料庫中,程式重啟後依然能夠從資料庫中獲取歷史資訊;