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)

用这样的方式重构了多个网页。
结构如下:
重构图谱

网页打开:
网页打开
测试通过~

引用链接:

猜你喜欢

转载自blog.csdn.net/qq_24495287/article/details/83513624