Flask-SQLAlchemy

Flask-SQLAlchemy

Flask-SQLAlchemy使用起來很是有趣,對於基本應用程序來講很是簡單,而且適用於大型應用程序。python

安裝mysql

pip install flask-sqlalchemy

配置

Flask-SQLAlchemy存在如下的配置值,Flask-SQLAlchemy從主Flask配置中加載這些值,能夠經過各類方式進行填充。請注意,在建立引擎後其中一些內容沒法修改,所以須要確保儘早的進配置,而且不要在運行時對其進行修改。sql

配置名稱 介紹
SQLALCHEMY_DATABASE_URI 將要被用於數據庫連接的URI。 例如: mysql://username:password@server/db mysql+pymysql://root:123456@localhost:3306/TTC
SQLALCHEMY_BINDS 一個將會綁定多種數據庫的字典。 更多詳細信息請看官文 綁定多種數據庫.
SQLALCHEMY_ECHO 若是設置爲True,SQLAlchemy會將記錄全部標準錯誤聲明,這對調試很是有用。
SQLALCHEMY_RECORD_QUERIES 能夠用於禁用或啓用查詢記錄的顯示 。 查詢記錄會自動的在調試或測試模式下進行 。
SQLALCHEMY_NATIVE_UNICODE 能夠用來啓用或禁用本地對 unicode 的支持。
SQLALCHEMY_POOL_SIZE 數據庫池的大小。 默認與數據庫引擎的值相同 (一般爲 5)
SQLALCHEMY_POOL_TIMEOUT 指定池的鏈接超時(以秒爲單位)。
SQLALCHEMY_POOL_RECYCLE 自動循環鏈接的秒數。這是MySQL所必須的,默認狀況下,閒置8小時後會刪除鏈接。若是使用MySQL,SQLAlchemy會自動將其設置爲2小時,一些後端可能使用不一樣的默認超時值。
SQLALCHEMY_MAX_OVERFLOW 控制鏈接池達到最大大小後還能夠建立的鏈接數,當這些附加鏈接返回到鏈接池時,它們將會被斷開並丟棄。
SQLALCHEMY_TRACK_MODIFICATIONS 若是設置爲True,Flask-SQLAlchemy將跟蹤對對象的修改,併發出信號。默認值爲None,他能夠啓用跟蹤功能,但會發出警告,代表它在未來會被默認禁用。這須要額外的內存,若是不須要,應該禁用。

下面對SQLAlchemy進行配置數據庫

app.pyflask

from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)  # 建立一個Flask app對象
# 數據庫連接的配置,此項必須,格式爲(數據庫+驅動://用戶名:密碼@數據庫主機地址:端口/數據庫名稱)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@localhost:3306/flask_ttc'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 跟蹤對象的修改,在本例中用不到調高運行效率,因此設置爲False
db = SQLAlchemy(app=app)  # 爲哪一個Flask app對象建立SQLAlchemy對象,賦值爲db
manager = Manager(app=app)  # 初始化manager模塊

@app.route('/')
def hello_world():
    reutrn 'Hello World!'

if __name__ == '__main__':
    manager.run()  # 運行服務器

聲明模型

這裏的模型就的咱們口中一般說的MTV中Model,顯然app.py 中用@app.route()裝飾器裝飾的就是View了,Templates中存在的html模板文件就的咱們的T了。後端

這裏簡單的寫一個Modelruby

models.pybash

from app import db  # 導入app文件中的SQLAlchemy對象

class Student(db.Model):  # 繼承SQLAlchemy.Model對象,一個對象表明了一張表
    s_id= db.Column(db.Integer, primary_key=True, autoincrement=True, unique=True)  # id 整型,主鍵,自增,惟一
    s_name = db.Column(db.String(20))  # 名字 字符串長度爲20
    s_age = db.Column(db.Integer, default=20)  # 年齡 整型,默認爲20

    __tablename__ = 'student'  # 該參數可選,不設置會默認的設置表名,若是設置會覆蓋默認的表名
    def __init__(self, name, age):  # 初始化方法,能夠對對象進行建立
        self.s_name = name
        self.s_age = age
    def __repr__(self):  # 輸出方法,與__str__相似,可是可以重現它所表明的對象
        return '<Student %r, %r, %r>' % (self.s_id, self.s_name, self.sage)

列的類型是Column的第一個參數。能夠直接指定他們,也能夠的調用他們以進一步的指定他們的長度。如下類型是最多見的:服務器

類型 介紹
Integer 一個整數
String(size) 一個字符串,並能夠設置它的最大長度
Text 更長的unicode文本
DateTime 經過Python的datetime對象來表示時間日期
Float 存儲一個浮點數
Boolean 存儲一個布爾值
PickleType 存儲一個序列化( Pickle )後的Python對象
LargeBinary 存儲巨大長度的二進制數據

咱們能夠經過交互式的環境來建立數據庫中的表

>>> from app import db  # 引入SQLAlchemy
>>> from models import *  # 映入加載了model的SQLAlchemy對象,db
>>> db.create_all()  # 建立表

這樣數據庫中就已經存在student表了

增刪改查(CURD)

這些操做均可以經過SQL語句來實現

sql = 'select * from student;'
stus = db.session.execute(sql)

插入(Create)

# 插入一條
stu = Student('TTC', 22)
db.session.add(stu)
db.session.commit()
# 若是添加的對象是列表,使用db.session.add_all(list)
stus = []
db.session.add_all(stus)
db.session.commit()

刪除(Delete)

stu = Student.query.get(1)  # 須要刪除的對象
db.session.delete(stu)  # 刪除
db.session.commit()  # 提交事務

修改(Update)

stu = Student.query.get(1)  # 須要修改的對象
stu.s_age = 18  # 修改值
db.session.commit()  # 提交

選擇(Select)

過濾查詢

stu = Student.query.filter(s_name='TTC').first()
# 若是查詢一個不存在的會返回一個None

用主鍵查詢

stu = Student.query.get(1)  # 主鍵查詢

比較查詢

# __lt__ 小於  __le__小於等於   __gt__ 大於  __ge__ 大於等於
Student.query.filter(Student.s_age.__lt__(16))  # 小於16歲 
Student.query.filter(Student.s_age.__le__(16))  # 小於等於16歲
Student.query.filter(Student.s_age.__gt__(16))  # 大於16歲
Student.query.filter(Student.s_age.__ge__(16))  # 大於等於16歲

In 查詢

# 使用in_方法獲取與列表中值相匹配的值
Student.query.filter(Student.s_age.in_([16, 17, 18, 19, 20]))

排序

Student.query.order_by('s_age') # 按年齡排序,默認升序,在前面加-號爲降序'-s_age'

限制條數和從第幾條開始

Student.query.filter(s_age=18).offset(2).limit(3)  # 跳過二條開始查詢,限制輸出3條

多條件查詢

Student.query.filter(Student.s_age == 18, Student.s_name == 'TTC')
# 也能夠經過and_而且  or_或者  not_非 的方法來進行查詢
Student.query.filter(and_(Student.s_age == 18, Student.s_name == 'TTC'))
Student.query.filter(or_(Student.s_age == 18, Student.s_name == 'TTC'))
Student.query.filter(not_(Student.s_age == 18, Student.s_name == 'TTC'))

模型關係

一對多(one-to-many)關係

最多見的關係就是一對多的關係。由於關係在它們創建以前就已經聲明,可使用字符串來指代尚未建立的類。

好比班級和學生的關係即爲一對多的關係,一個班級對應多名學生。

models.py

from app import db

class Grade(db.Model):
    """班級表"""
    g_id = db.Column(db.Integer, primary_key=True, autoincrement=True)  # 班級id
    g_name = db.Column(db.String(20))  # 班級名稱
    g_desc = db.Column(db.String(100))  # 描述
    students = db.relationship('Student', backref='grade', lazy=True)  # 關係

    __tablename__ = 'grade'  # 表名

    def __init__(self, name, desc):  # 初始化方法
        self.g_name = name  # 名稱
        self.g_desc = desc  # 描述

    def __repr__(self):  # 輸出方法,顯示對象內容
        return '<Grade %r, %r, %r>' % (self.g_id, self.g_name, self.g_desc)

class Student(db.Model):
    """學生表"""
    s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)  # 學生ID
    s_name = db.Column(db.String(20))  # 學生姓名
    s_age = db.Column(db.Integer, default=20)  # 學生年齡
    g_id = db.Column(db.Integer, db.ForeignKey('grade.g_id'))  # 外鍵

    __tablename__ = 'student'  # 表名

    def __init__(self, name, age, g_id):  # 初始化方法
        self.s_name = name  # 姓名
        self.s_age = age  # 年齡
        self.g_id = g_id  # 班級ID

    def __repr__(self):  # 輸出方法,顯示對象內容
        return '<Student %r, %r, %r>' % (self.s_id, self.s_name, self.s_age)

經過學生獲取班級

g_id = Student.query.get(12).grade.g_id

經過班級獲取學生

stus = Grade.query.get(2).students

一對一(one-to-one)關係

須要使用一對一的關係,和一對多的關係的寫法是同樣的,只是在relationship中有一個參數不一樣,須要將uselist=Flase,這樣兩個表之間的關係就變成了一對一的關係。其參數的含義就是不使用列表,兩個表之間只有一條對應一條的關聯。

多對多(many-to-many)關係

若是想使用多對多關係,須要定義一一個用於關係的輔助表,對於這個輔助表,建議不使用模型,而是採用一個實際的表:

咱們接着以前的寫,加入學生(Student)和課程(Course)的關係

from app import db  # 引入模塊
class Student(db.Model):
    """學生表"""
    s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)  # 學生ID
    s_name = db.Column(db.String(20))  # 學生姓名
    s_age = db.Column(db.Integer, default=20)  # 學生年齡
    g_id = db.Column(db.Integer, db.ForeignKey('grade.g_id'))  # 班級ID

    __tablename__ = 'student'  # 學生表

    def __init__(self, name, age, g_id):  # 初始化方法
        self.s_name = name  # 名稱
        self.s_age = age  # 年齡
        self.g_id = g_id  # 班級ID

    def __repr__(self):  # 格式化輸出顯示對象中的值
        return '<Student %r, %r, %r>' % (self.s_id, self.s_name, self.s_age)

# 輔助表 記錄學生表和課程表的多對多關係
sc = db.Table('sc',  # 表名
              db.Column('s_id', db.Integer, db.ForeignKey('student.s_id'), primary_key=True),
              db.Column('c_id', db.Integer, db.ForeignKey('course.c_id'), primary_key=True)
              )

class Course(db.Model):
    """課程表"""
    c_id = db.Column(db.Integer, primary_key=True, autoincrement=True)  # 課程的ID
    c_name = db.Column(db.String(20))  # 課程名稱
    students = db.relationship('Student', secondary=sc, backref='courses')  # 與學生表的關係
    # secondary指定副表名稱
    def __init__(self, name):  # 初始化方法
        self.c_name = name  # 課程名

    def __repr__(self):  # 格式化輸出顯示對象中的值
        return '<Course %r, %r >' % (self.c_id, self.c_name)

多對多關係的數據插入方式

stu = Student.query.get(s_id)  # 獲取學生對象
cou = Course.query.get(c_id)  # 獲取課程對象
# 方式一
cou.students.append(stu)  # 創建學生和課程的關係
db.session.add(cou)  # 爲會話添加事務
# 方式二
stu.courses.append(cou)
db.session.add(stu)
# 方式一和方式二等效

db.session.commit()  # 提交事務

多對多關係的數據刪除方式

stu = Student.query.get(s_id)
cou = Course.query.get(c_id)
# 方式一
cou.students.remove(stu)

# 方式二
stu.students.remove(cou)

# 方式一和方式二等效

db.session.commit()

多對多關係互相查詢

經過學生查課程

cous = Student.query.get(s_id).courses

經過課程查學生

stus = Course.query.get(c_id).students
相關文章
相關標籤/搜索