
timg (9).jpg
從本章開始,逐漸引入資料庫相關知識點。
關于資料庫的工具以及一些入門的知識請自行查找資料學習(例如:建立資料表,資料庫可視化工具)。
資料表建立方式
image.png
對于我們開發人員來說,一般推薦使用Code First ,因為可以專注業務模型的設計 而不是資料庫設計 , 資料庫隻是用來存資料的 ,它的表關系應該由我們業務來決定。
那麼其他兩種資料表建立方式可以自己上網查詢相關資料,這裡不再贅述。
定義一個模型類
之前提過一個叫做驗證層,現在引入模型層(MVC中的M:模型層)
設計模型的思維,應該考慮業務模型,而不要去過多注意資料庫的設計,資料庫隻是存資料的。
app檔案夾下建立models檔案夾并建立一個名為book.py的模型:
這裡使用sqlalchemy這個包來做模型映射,還有一個包叫做flask_sqlalchemy,是flask在sqlalchemy的基礎上做了一些自己的封裝,待會我們也要用到。
再介紹一個第三方的獨立的包:WTFORMS,Flask也針對這個包做了封裝并有一個新的包叫做Flask_WTFORMS,以上兩個(sqlalchemy、WTFORMS)是獨立的兩個包,可以用在任何時候而不僅僅在Flask中。
Flask的路由是在werkzeug基礎上封裝的
Flask是微架構,隻提供最核心的功能其他部分可以自由組裝
所有flask插件都必須和flask核心對象app綁定在一起
安裝兩個包:
pip install sqlalchemy
pip install flask-sqlalchemy
編輯book.py:
from sqlalchemy import Column, Integer, String
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Book(db.Model):
# 主鍵 自增
id = Column(Integer, primary_key=True, autoincrement=True)
# 長度50 不為空
title = Column(String(50), nullable=False)
author = Column(String(30), default="未知")
# unique : 不重複, 會加一個索引, 不重複
uid= Column(String(15), nullable=False, unique=True)
以上代碼就是一個簡單的建立資料表的模型,包含四個字段,
之前提到過,所有的Flask的插件都需要和Flask的核心對象app來關聯起來,那麼怎麼做關聯呢?
在app檔案夾下的
__init__.py
中:
from flask import Flask
from app.models.book import db
def create_app():
app = Flask(__name__)
app.config.from_object("app.setting")
app.config.from_object("app.secure")
register_blueprint(app)
db.init_app(app)
db.create_all(app=app)
return app
def register_blueprint(app):
from app.web import web
app.register_blueprint(web)
首先把db對象導入,
再使用db.init_app(app)做關聯,init_app這個方法很重要,後邊所有的Flask插件都使用這個方法做關聯。
接着,
需要把資料庫的配置資訊放到配置檔案中,因為資料庫配置資訊是屬于比較機密的,是以我們放在secure.py中。
SQLALCHEMY_DATABASE_URI = 'mysql+cymysql://root:[email protected]:3306/demo'
上邊配置資訊的變量名
SQLALCHEMY_DATABASE_URI
這個是不可以更改的,必須使用這個,
後邊參數的意思是使用cymysql這個驅動來做資料庫操作,使用者名root 密碼 123456,ip 端口是127.0.0.1 3306,資料庫名為demo。
cymysql需要安裝:
pip install cymysql
運作代碼檢視結果,資料庫确實多了一張名為book的表。
ORM與Code First
ORM 對象關系映射 : 包含的層面更廣闊 不僅僅是建立 還包含查詢 更新 删除
與
Code First : 解決的是資料表建立的問題,專注業務模型設計而不是資料庫設計,資料庫隻是存資料的,表關系應該有業務來決定
業務邏輯最好寫在MVC中M中
Flask中上下文管理
- 應用上下文(AppContext)
- 請求上下文(RequestContext)
上下文本質來說其實就是對象
應用上下文:對核心對象Flask的封裝
請求上下文:對請求對象Request的封裝
為什麼會需要上下文?直接操作Flask核心對象不行嗎?
其實這個就是一個設計思想的問題,有時候對于一個對象來說,有一些資訊是屬于這個對象外部的,并不是屬于對象本身,那麼此時我們可以設計一個所謂的上下文(上下文就是一個對象),把Flask核心對象和外部的這些資料一起組成一個整體,這個整體就是我們說的上下文對象。
Flask核心對象:承載着各種各樣的功能,例如:儲存配置檔案資訊、提供注冊路由\視圖函數等這樣的功能。
AppContext :把Flask核心對象做了一系列封裝,并且附加了一些額外的參數
Request :儲存了一些請求資訊,例如: URL參數,完整的URL等等一切的請求資訊都在這個對象中。
RequestContext : 對Request對象的封裝。
在我們編碼過程中,真正想去使用的是Flask核心對象或者是Request這個對象,但是我們要使用它并不一定要直接直接導入這倆核心對象,正确的做法是:
從AppContext或RequestContext間接的去拿Flask核心對象或者是Request。
Flask中,采用了LocalProxy模式(本地代理)的模式提供了間接去操作上下文的能力,也就是current_app和request這兩個對象。
這裡Flask使用了設計模式裡邊的代理模式。
Flask上下文與出入棧
Flask如何操作上下文?看下圖:
當一個請求進入Flask架構中時,首先會執行個體化一個RequestContext(請求上下文),這個請求上下文封裝了這次請求的相關資訊,請求的相關資訊在Request中,然後會把請求上下文使用push方法推入到棧中(棧:先入後出),Flask中使用 LocalStack 來表示一個棧,LocalStack 是一個對象,執行個體化之後,用 _request_ctx_stack 來表示RequestContext推入的棧,同樣的,還有一個 _app_ctx_stack 也是一個棧,
RequestContext在入棧之前,Flask會去檢查一下 _app_ctx_stack 這個棧的棧頂的元素,如果是空或者不是目前對象,那麼Flask會把AppContext推入_app_ctx_stack這個棧中
然後才會把RequestContext推入_request_ctx_stack棧中。
current_app(Local Proxy) 和 request(Local Proxy) 永遠都是指向棧頂的,是以當你去使用current_app或request,其實就是在操作這兩個棧的棧頂元素。
欲知後事如何,請看下回分解,記得點個贊~感謝