Codeforces Beta Round #73(Div2)補題報告
SQLALchemy 實際上是對資料庫的抽象,讓開發者不用直接和 SQL 語句打交道,而是通過 Python 物件來操作資料庫,在捨棄一些效能開銷的同時,換來的是開發效率的較大提升
SQLAlchemy是一個關係型資料庫框架,它提供了高層的 ORM 和底層的原生資料庫的操作。
flask-sqlalchemy 是一個簡化了 SQLAlchemy 操作的flask擴充套件。
文件地址:http://docs.jinkan.org/docs/flask-sqlalchemy
安裝
安裝 flask-sqlalchemy pip install flask-sqlalchemy 如果連線的是 mysql 資料庫,需要安裝 mysqldb pip install flask-mysqldb 資料庫連線設定 在 Flask-SQLAlchemy 中,資料庫使用URL指定,而且程式使用的資料庫必須儲存到Flask配置物件的 SQLALCHEMY_DATABASE_URI 鍵中 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test' 其他設定: # 動態追蹤修改設定,如未設定只會提示警告 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True #查詢時會顯示原始SQL語句 app.config['SQLALCHEMY_ECHO'] = True 配置完成需要去 MySQL 中建立專案所使用的資料庫 $ mysql -uroot -pmysql $ create database test charset utf8;
其它配製
名字 備註 SQLALCHEMY_DATABASE_URI 用於連線的資料庫 URI 。例如:sqlite:////tmp/test.dbmysql://username:password@server/db SQLALCHEMY_ECHO 如果設定為Ture, SQLAlchemy 會記錄所有 發給 stderr 的語句,這對除錯有用。(列印sql語句) SQLALCHEMY_RECORD_QUERIES 可以用於顯式地禁用或啟用查詢記錄。查詢記錄 在除錯或測試模式自動啟用。更多資訊見get_debug_queries()。 SQLALCHEMY_POOL_SIZE 資料庫連線池的大小。預設是引擎預設值(通常 是5 ) SQLALCHEMY_POOL_TIMEOUT 設定連線池的連線超時時間。預設是 10 。 SQLALCHEMY_COMMIT_ON_TEARDOWN 資料庫內容傳送改變之後,自動提交
常用的SQLAlchemy欄位型別
常用的SQLAlchemy列選項
常用的SQLAlchemy關係選項
資料庫基本操作
在Flask-SQLAlchemy中,插入、修改、刪除操作,均由資料庫會話管理。
會話用 db.session 表示。在準備把資料寫入資料庫前,要先將資料新增到會話中然後呼叫 commit() 方法提交會話。
在 Flask-SQLAlchemy 中,查詢操作是通過 query 物件操作資料。最基本的查詢是返回表中所有資料,可以通過過濾器進行更精確的資料庫查詢。
在檢視函式中定義模型類
from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) #設定連線資料庫的URL app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True #查詢時會顯示原始SQL語句 app.config['SQLALCHEMY_ECHO'] = True db = SQLAlchemy(app) class Role(db.Model): # 定義表名 __tablename__ = 'roles' # 定義列物件 id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) us = db.relationship('User', backref='role') #repr()方法顯示一個可讀字串 def __repr__(self): return 'Role:%s'% self.name class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True, index=True) email = db.Column(db.String(64),unique=True) password = db.Column(db.String(64)) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) def __repr__(self): return 'User:%s'%self.name if __name__ == '__main__': app.run(debug=True)View Code
CRDB(增刪改查)
#建立表: db.create_all() #刪除表 db.drop_all() #插入一條資料 ro1 = Role(name='admin') db.session.add(ro1) db.session.commit() #再次插入一條資料 ro2 = Role(name='user') db.session.add(ro2) db.session.commit() #插入多條記錄 us1 = User(name='wang',email='[email protected]',password='123456',role_id=ro1.id) us2 = User(name='zhang',email='[email protected]',password='201512',role_id=ro2.id) db.session.add_all([us1,us2]) db.session.commit()View Code
查詢
常用的SQLAlchemy查詢過濾器
常用的SQLAlchemy查詢執行器
user = User.query.first() user.name = 'dong' db.session.commit() User.query.first()View Code
#filter_by精確查詢 #返回名字等於wang的所有人 User.query.filter_by(name='wang').all() #過濾名字 #first()返回查詢到的第一個物件 User.query.first() #all()返回查詢到的所有物件 User.query.all() #查詢所有物件 #filter模糊查詢,返回名字結尾字元為g的所有資料。 User.query.filter(User.name.endswith('g')).all() #模糊查詢 #get():引數為主鍵,如果主鍵不存在沒有返回內容 User.query.get() #邏輯非,返回名字不等於wang的所有資料 User.query.filter(User.name!='wang').all() #邏輯非 #not_ 相當於取反 from sqlalchemy import not_ User.query.filter(not_(User.name=='chen')).all() #取反 #邏輯與,需要匯入and,返回and()條件滿足的所有資料 from sqlalchemy import and_ User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all() #邏輯與 #邏輯或,需要匯入or_ from sqlalchemy import or_ User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()View Code
刪除
user = User.query.first()
db.session.delete(user)
db.session.commit()
User.query.all()
View Code
更新資料
模型之前的關聯
一對多
class Role(db.Model): ... #關鍵程式碼 us = db.relationship('User', backref='role', lazy='dynamic') ... class User(db.Model): ... role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))View Code
其中realtionship描述了Role和User的關係。在此文中,第一個引數為對應參照的類"User"
第二個引數backref為類User申明新屬性的方法
第三個引數lazy決定了什麼時候SQLALchemy從資料庫中載入資料
如果設定為子查詢方式(subquery),則會在載入完Role物件後,就立即載入與其關聯的物件,這樣會讓總查詢數量減少,但如果返回的條目數量很多,就會比較慢
設定為 subquery 的話,role.users 返回所有資料列表
另外,也可以設定為動態方式(dynamic),這樣關聯物件會在被使用的時候再進行載入,並且在返回前進行過濾,如果返回的物件數很多,或者未來會變得很多,那最好採用這種方式
設定為 dynamic 的話,role.users 返回查詢物件,並沒有做真正的查詢,可以利用查詢物件做其他邏輯,比如:先排序再返回結果
關聯查詢示例:
角色和使用者的關係是一對多的關係,一個角色可以有多個使用者,一個使用者只能屬於一個角色。
#查詢角色的所有使用者 #查詢roles表id為1的角色 ro1 = Role.query.get(1) #查詢該角色的所有使用者 ro1.us.all() #查詢使用者所屬角色 #查詢users表id為3的使用者 us1 = User.query.get(3) #查詢使用者屬於什麼角色 us1.roleView Code
多對多
registrations = db.Table('registrations', db.Column('student_id', db.Integer, db.ForeignKey('students.id')), db.Column('course_id', db.Integer, db.ForeignKey('courses.id')) ) class Course(db.Model): ... class Student(db.Model): ... courses = db.relationship('Course',secondary=registrations, backref='students', lazy='dynamic')View Code