1. 程式人生 > >flask+SQLAlchemy使用blueprint模組化

flask+SQLAlchemy使用blueprint模組化

flask使用blueprint模組化

原來我們的flask程式是寫在一個檔案裡的,但是這非常不利於python的程式碼模組化以及程式碼優美的作用,所以當代碼越寫越長時,模組化的需求就產生了。

經過多次踩坑以及藉助谷歌大法實現了原始碼的模組化,整理了一下單檔案重構的方式,現在整理出來幫助自己梳理和分享交流。

我們的程式碼重構包括兩塊:

  • flask+SQLAlchemy
  • flask+blueprint

flask+SQLAlchemy

SQLAlchemy使用簡介

閱讀廖老師寫的SQLAlchemy,對SQLAlchemy有了初步的瞭解。詳情可見引用連結。
簡單介紹下就是:
資料庫表是一個二維表,包含多行多列。用python的資料結構表示出來的話,就是一個list,每個元素是一個tuple,表示一行記錄,比如id和name:

[
    ('1', 'Michael'),
    ('2', 'Bob'),
    ('3', 'Adam')
]

由於tuple很難看出表的結構,如果把一個tuple用class的例項表示,則看起來更清晰些:

class User(object):
    def __init__(self, id, name):
        self.id = id
        self.name = name

[
    User('1', 'Michael'),
    User('2', 'Bob'),
    User('3', 'Adam')
]

這叫ORM技術:Object-relational mapping,把關係資料庫的表結構對映到物件上。其中有名的框架就是SQLAlchemy.
用法如下:

from flask import Flask, request
from flask_json import FlaskJSON, JsonError, json_response, as_json
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy

app.config['SQLALCHEMY_DATABASE_URI'] = r"sqlite:///%s/demo_new.db"%os.path.dirname(os.path.abspath(__file__))

FlaskJSON(app)
CORS(app)
db = SQLAlchemy(app)
db.create_all()
db = SQLAlchemy(app)
db.create_all()

class BusinessTree(db.Model):
    __tablename__ = 'business_tree'
    id = db.Column('id', db.Integer, primary_key=True, nullable=False)
    name = db.Column(db.String(255), nullable=False)
    json_tree = db.Column(db.String(), nullable=False)
    update_time = db.Column(db.DateTime, nullable=False)

以上是定義businessTree的類,表名為business_tree,表有4個欄位,類的4個變數定義了這四個值,分別對映到物件中的id,name,json_tree,update_time.
用 Column來定義一個列。類名就是你把賦給的那個變數的名字。如果你想要在表中使用不同的名字,你可以提供一個想要的列名的字串作為可選第一個引數。主鍵用 primary_key=Ture 標記。可以把多個鍵標記為主鍵,此時它們作為複合主鍵。

SQLAlchemy模組化

當有多個表時,那就對應著多個類,每個類可以拆成多個檔案,便於理解以及自定義。

當我們拆分時發現類是繼承基類db.model,而flask_sqlalchemy模組並不需要與app一起初始化,可以使用空的代替,
例如:

# apps.members.models
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Member(db.Model):
    # fields here
    pass

而應用啟動時,可以使用以下方式初始化:

# apps.application.py
from flask import Flask
from apps.members.models import db

app = Flask(__name__)
# later on
db.init_app(app)

可以在每個類中import db.
拆分框架如下:

# apps.shared.models
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()
# apps.members.models
from apps.shared.models import db

class Member(db.Model):
    # TODO: Implement this.
    pass
# apps.reporting.members
from flask import render_template
from apps.members.models import Member

def report_on_members():
    # TODO: Actually use arguments
    members = Member.filter(1==1).all()
    return render_template("report.html", members=members)
from flask import Blueprint
from apps.reporting.members import report_on_members

reporting = Blueprint("reporting", __name__)

reporting.route("/member-report", methods=["GET","POST"])(report_on_members)
# apps.application
from flask import Flask
from apps.shared import db
from apps.reporting.routes import reporting

app = Flask(__name__)
db.init_app(app)
app.register_blueprint(reporting)

這裡框架中已經用到了blueprint,具體的下一節再細說。當前的模組化通過抽出db類,可以實現表的拆分。

flask+blueprint

為什麼使用藍圖

為了在一個或多個應用中,使應用模組化並且支援常用方案, Flask 引入了 藍圖 概念。藍圖可以極大地簡化大型應用併為擴充套件提供集中的註冊入口。 Blueprint 物件與 Flask 應用物件的工作方式類似,但不是一 個真正的應用。它更像一個用於構建和擴充套件應用的 藍圖 。

Flask 中的藍圖不是一個可插撥的應用,因為它不是一個真正的應用,而是一套可以 註冊在應用中的操作,並且可以註冊多次。那麼為什麼不使用多個應用物件呢?可以 使用多個應用物件(參見 應用排程 ),但是這樣會導致每個應用都使 用自己獨立的配置,且只能在 WSGI 層中管理應用。

而如果使用藍圖,那麼應用會在 Flask 層中進行管理,共享配置,通過註冊按需改 變應用物件。藍圖的缺點是一旦應用被建立後,只有銷燬整個應用物件才能登出藍圖。

如何使用藍圖

這裡一開始是這樣定義的:

from flask import Blueprint
business_detail=Blueprint('business_detail',__name__)
@business_detail.route('/business_xxx',methods=['GET', 'POST'])
@as_json
def business_detail():
   pass

但是出現了這樣的報錯:
AttributeError: 'function' object has no attribute 'name'
網上搜索這個錯誤後,找到了這樣的解釋:
檢視和blueprint不能用同樣的名字,因為你這樣替換了全域性變數指向bluepeint的business_detail,用相同的全域性名字去註冊route函式,將blueprint重新取一個名字即可,修改後如下:

from flask import Blueprint
business_detail_bp=Blueprint('business_detail',__name__)
@business_detail_bp.route('/business_xxx',methods=['GET', 'POST'])
@as_json
def business_detail():
   pass

然後在flask呼叫的頁面中註冊呼叫:

from routes.business_tree import business_tree_bp
app.register_blueprint(business_tree_bp)

用這樣的方式重構了多個網頁。
結構如下:
重構圖譜

網頁開啟:
網頁開啟
測試通過~

引用連結: