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)
用這樣的方式重構了多個網頁。
結構如下:
網頁開啟:
測試通過~
引用連結: