flask-sqlalchemy


3.1 連接數據庫:

首先切入到我們的虛擬環境 ,安裝我們的 Flask-SQLchemy

pip install flask-sqlalchemy
pip install pymysql

這里我們的DBMSmysql數據庫為例, 連接數據庫

實例

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
HOST = '127.0.0.1'
PORT = '3306'
DATABASE_NAME = '01_db'
USERNAME = 'root'
PASSWORD = 'root'

DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{databasename}?charset=utf8mb4"\
.format(username=USERNAME,password=PASSWORD,host=HOST,port=PORT,databasename=DATABASE_NAME)

app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']= False


db = SQLAlchemy(app)

解讀:

1 從flask_sqlalchemy模塊中導入SQLAlchemy

from flask_sqlalchemy import SQLAlchemy

2 app對象通過變量SQLALCHEMY_DATABASE_URI加載配置好的URI(統一資源標識符),URI內包含了各種用於連接數據庫的信息,指向一個具體的庫。

常用數據庫的URI格式

HOST = '127.0.0.1'  # ip
PORT = '3306'       # 端口
USERNAME = 'root'   # 數據庫賬號
PASSWORD = 'root'   # 密碼
DATABASE_NAME = '01_db'  # 具體的一個庫名
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{databasename}?charset=utf8mb4"\
.format(username=USERNAME,password=PASSWORD,host=HOST,port=PORT,databasename=DATABASE_NAME)

app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI

SQLALCHEMY_TRACK_MODIFICATIONS這個配置變量決定是否追蹤對象的修改,這用於FLask- SQLALchemy的事件通知系統。這個配置鍵默認值為None,如果沒有特殊需要我們把它設置為Flase, 避免造成一些沒必要的性能浪費。

app.config['SQLALCHEMY_TRACK_MODIFICATIONS']= False

SQLAlchemy類傳入app類,引用app配置定位到具體的數據庫,並且實例化出db對象,這個db對象代表我們的數據庫,並且通過這個對象操作我們的ORM

db = SQLAlchemy(app)

3.2 數據庫模型

1554281734348

3.2.1 什么是數據庫模型?

繼承了db.Model的python類,並且這個python類映射到數據庫為一個表,這個python類稱之為數據庫模型。每個數據庫模型都對應着數據庫中的一個表。

3.2.2 數據庫模型實例:

class UserInfo(db.Model):
    __tablename__ = 'user_info'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    username = db.Column(db.String(20),nullable=False)
  • __tablename__可以直接指定表名(推薦使用)。如果沒有寫__tablename__指定表名,此類名可以自動轉化為表名(不推薦使用)。
    • 類名自動轉化表名的方式為User--> user# 單個單詞轉換為小寫
      UserInfo--> user_info# 多個單詞轉換為小寫並使用下划線分隔
    • 如UserInfo類在沒有__tablename__指定表名時候,UserInfo類會自動映射到數據庫的表名為user_info
  • db.Column類實例化表示字段(表示數據庫中的列),該類實例化出的對象被一個變量接受,該變量表示字段名。該類實例化時傳入的參數表示字段的約束。
    • 如:id = db.Column(db.Integer,primary_key=True,autoincrement=True)表示該表內id字段為主鍵並且自動增長。

1554281780499

3.2.3 常用的字段類型表:

字段 說明 映射到數據庫對應類型
Integer 整數 int類型
String 字符串,String類內可選擇length參數的值用於設置最大字符個數 varchar類型
Text 用於儲存較長的Unicode文本,,理論上可以儲存65535個字節 text類型
Date 日期,存儲Pythondatetime.date 對象 date類型
Time 時間,存儲Pythondatetime.time 對象 time類型
DateTime 時間和日期,存儲Python 的datetime 對象 datetime類型
Float 浮點類型 float類型
Double 雙精度浮點類型,比浮點類型小數位精度更高。 double類型,占據64位。
Boolean 布爾值 tinyint類型
Enum 枚舉類型 enum類型

3.2.4 Column常用參數表:

約束 說明
primary_key 如果設為True,該列就是表的主鍵
unique 如果設為True,該列每個值唯一,也就是該字段不允許出現重復值
index 如果設為True,為這列創建索引,用於提升查詢效率
nullable 如果設為True,這列允許使用空值,反之則不允許使用空值。
server_default 為這列定義默認值, 默認值只支持字符串,其他類型需要db.text()方法指定
default 為這列定義默認值,但是該約束並不會真正映射到表結構中,該約束只會在ORM層面實現(不推薦使用)
comment 該字段的注釋
name 可以使用該參數直接指定字段名
autoincrement 設置這個字段為自動增長的。
server_default常用配置
配置默認值類型 代碼
更新datatime時間 server_default = db.text("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
當前的datatime時間 server_default = db.text("CURRENT_TIMESTAMP")
數字 server_default=“數字”
布爾 server_default=db.text('True') / server_default=db.text('False')/ server_default='數字'

1554281889712

3.2.5 將寫好的模型映射到數據庫。

class UserInfo(db.Model):
    __tablename__ = 'user_info'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    username = db.Column(db.String(20),nullable=False)
    
db.create_all()

如果你已經定義好了一個繼承db.Model的類,我們把這個類稱之為模型。我們想把這個模型映射到數據庫中,也就是在數據庫中創建這個模型所描述的一張表,使用db.create_all()可以實現把繼承了該db.model的所有模型創建到數據庫中。查看數據庫的時候我們會發現多了一張user_info表。

1549800892083

3.2.6 更新模型

如果我們要更新一個模型,並且想把這個新的模型映射到數據庫中,直接使用db.create_all()會無效,因為原來已經存在了這張表,為了解決這個問題我們可以先db.drop_all()刪除該庫下的所有繼承了db.model的模型表,然后再db.create_all()使得繼承了db.model的所有模型表映射到數據庫中,從而創建我們更新的表。這種方式的原理是先刪除數據庫中原來所有的模型表,然后在新建所有需要映射的模型表,這種方式的弊端是它把數據庫中原有的數據都銷毀了。

為了解決這種更新模型導致刪除掉原來的數據的弊端。下一章將會介紹一種更好的方式用於更新數據庫。

1554281934788

3.3 數據庫操作

3.3.1 增

模型表 映射到數據中

class School(db.Model):
    __tablename__ = "school"
    id = db.Column(db.Integer,primary_key=True,nullable=False,autoincrement=True,comment="ID")
    name = db.Column(db.String(30),nullable=False,server_default='',comment="學校名稱")
    area = db.Column(db.String(30),nullable=False,server_default='',comment="所屬地區")
    score = db.Column(db.Integer,nullable=False,server_default='600',comment="錄取分數線")
    def __repr__(self):
        return "<School(name:{})>".format(self.name)

db.create_all()

實例3.3.1.1: 新增實例

新增四條記錄映射到數據庫中

school_01 =School(name="北京大學",area="北京",score=658)  # 實例化模型類作為一條記錄
school_02 =School(name="清華大學",area="北京",score=667)
school_03 =School(name="中山大學",area="廣東",score=645)
school_04 =School(name="復旦大學",area="上海",score=650)

db.session.add(school_01)   # 把新創建的記錄添加到數據庫會話
db.session.add(school_02)
db.session.add(school_03)
db.session.add(school_04)

db.session.commit()  # 提交數據庫會話

提示:數據庫會話db.session和后面介紹的Flasksession對象沒有關系。db.session是數據庫會話也稱為事務。

  1. 實例化模型類創建對象,該對象作為一條記錄,實例化的過程傳入的參數為字段內容。
  2. 把新創建的記錄添加到數據庫會話。
  3. 提交數據庫會話

查看數據庫

1549869497823

提示1 :如果add多條記錄可以使用add_all()一次添加包含多條記錄的列表

如:db.session.add_all([school_01,school_02,school_03,school_04])

3.3.2 查

在我們的flask中db.session出的對象調用query屬性,可以通過query屬性調用各種過濾方法完成查詢。

模型類.<過濾方法>.<查詢方法>

常用過濾器表:

過濾器 說明
filter() 使用指定的規則過濾記錄相當於sql的where約束條件,返回一個新查詢
filter_by() 同filter原理,不同的是查詢的時要使用關鍵字參數,返回一個新查詢
limit() 使用指定的值限制原查詢返回的結果的數量,返回一個新查詢
offset() 偏移原查詢返回的結果,返回一個新查詢
order_by() 根據指定條件對原查詢結構進行排序,返回一個新查詢
group_by() 根據指定條件對原來查詢結構進行分組,返回一個新查詢

實例3.3.2.1: 查詢實例

下面幾個查詢案例需要在實例3.3.1完成的基礎上操作

all()返回一個列表,列表里存放所有符合條件的記錄

all_school = School.query.all()
print(all_school) 

# 輸出:[<School(name:北京大學)>, <School(name:清華大學)>, <School(name:中山大學)>, <School(name:復旦大學)>]

first()返回符合條件的第一條記錄:

school_01 =School.query.first()
print(school_01)

# 輸出:<School(name:北京大學)>

get()返回指定主鍵值(id字段)的記錄:

school_01 = School.query.get(1)
print(school_01)

#輸出:<School(name:北京大學)>

filter() 使用指定的規則過濾記錄相當於sql的where約束條件,返回新產生的查詢對象。

beijing_all = School.query.filter(School.area == "北京").all()
beijing_first = School.query.filter(School.area == "北京").first()
print(beijing_all)
print(beijing_first)

# 輸出:[<School(name:北京大學)>, <School(name:清華大學)>]
#       <School(name:北京大學)>

filter_by:同filter()效果一樣,查詢的時候使用關鍵字參數查詢(無法進行多表復雜查詢,不推薦使用)

zhongshan_school = School.query.filter_by(name='中山大學').all()
print(zhongshan_school)

# 輸出:[<School(name:中山大學)>]

db.session.qury(模型類)等價於模型類.query,db.session.qury功能更強大一些,可以進行多表查詢。

fudan_school = School.query.filter(School.name == '復旦大學').first()
print(fudan_school)  
# 輸出:<School(name:復旦大學)>

fudan_school = db.session.query(School).filter(School.name == '復旦大學').first()
print(fudan_school)
# 輸出:<School(name:復旦大學)>

提示:其他的過濾器會在接下來的章節具體根據實際案例講解

3.3.3 改

實例3.3.3.1: 修改實例

修改北京大學的錄取成績

beida = School.query.filter(School.name=='北京大學').first()
beida.score = 630
db.session.commit()

1549872535950

更新一條記錄分為一下幾部:

  1. 找到對應的記錄對象

  2. 修改記錄對象的屬性

  3. 直接調用db.session.commit()提交會話

    提示:只有要插入新的記錄或要將現有的記錄添加到會話中時才需要使用add()方法。只是更新現有記錄的時可以修改記錄對象屬性后直接提交會話

3.3.4 刪

實例3.3.4.1: 刪除實例

從數據庫中刪除清華大學相關信息

qinghua = School.query.filter(School.name=='清華大學').first()
db.session.delete(qinghua)
db.session.commit()

1549872948198

刪除一條記錄分為以下幾步:

  1. 找到對應的記錄對象
  2. 需要調用delete()方法在會話中標識需要刪除的記錄,具體是把該記錄對象傳入db.session.delete(記錄對象)實現標識。
  3. 調用db.session.commit()提交會話。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM