约定俗成的Flask项目结构

一.使用工厂函数创建程序实例

工厂(factory)是指创建其他对象的对象,通常是一个返回其他类的对象的函数或方法。程序实例在工厂函数中创建,这个函数返回程序实例app。按照惯例,这个函数被命名为create_app()或make_app()。我们把这个工厂函数称为程序工厂(Application Factory)——即“生产程序的工厂”,使用它可以在任何地方创建程序实例。

工厂函数提供了很大的灵活性。另外,借助工厂函数,我们还可以分离扩展的初始化操作。==在这个工厂函数中,我们会创建程序实例,为其加载配置,注册蓝本,执行扩展的初始化操作.最后返回程序实例==。

约定俗成:

项目根目录中(app.py同级)创建工厂文件factory.py

image.png

1
2
3
4
5
6
7
8
9
10
11
12
csharp复制代码from flask import Flask


def create_app():
app = Flask(__name__)
# 加载配置

# 注册蓝本

# 初始化扩展

return app

此时app.py调用create_app()获取程序实例app

1
2
3
4
5
6
7
8
9
10
11
python复制代码from factory import create_app

app = create_app()

@app.route('/')
def hello_world():
return 'Hello World!'


if __name__ == '__main__':
app.run()

二.使用类组织配置文件

在实际需求中,我们往往需要不同的配置组合。例如,开发用的配置,测试用的配置,生产环境用的配置.我们可以在单个配置文件中使用Python类来组织多个不同类别的配置。

约定俗成:

项目根目录中(app.py同级)创建配置文件settings.py

1
2
3
4
5
6
7
8
9
10
11
12
ruby复制代码# @FileName: settings
class BaseConfig(object):
# 基础配置

class DevelopmentConfig(BaseConfig):
# 开发环境配置

class TestConfig(BaseConfig):
# 测试环境配置

class ProductionConfig(BaseConfig):
# 生产环境(上线环境)配置

在配置文件的底部,我们创建了一个存储配置名称和对应配置类的字典config,用于在创建程序实例时通过配置名称来获取对应的配置类

工厂函数中加载配置

在创建程序实例后使用app.config.from_object()方法加载配置,传入配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
csharp复制代码//factory.py
from flask import Flask
import settings


def create_app():
app = Flask(__name__)
# 加载配置
app.config.from_object(settings.DevelopmentConfig)
# 注册蓝图

# 初始化扩展

return app

三.扩展类实例化和初始化分离

为了完成扩展的初始化操作,我们需要在实例化扩展类时传入程序实例。但使用工厂函数时,并没有一个创建好的程序实例可以导入。如果我们把实例化操作放到工厂函数中,那么我们就没有一个全局的扩展对象可以使用,比如表示数据库的db对象。

为了解决这个问题,大部分扩展都提供了一个init_app()方法来支持分离扩展的实例化和初始化操作。现在我们仍然像往常一样初始化扩展类,但是并不传入程序实例.这时扩展类实例化的工作可以抽离出来

约定俗成:

项目根目录中(app.py同级)创建用于扩展类实例化的文件extensions.py

以flask-sqlalchemy扩展为例

1
2
3
4
5
6
ini复制代码# @FileName: extendsions
from flask_sqlalchemy import SQLAlchemy

#扩展类实例化
db = SQLAlchemy()
#......

image.png

四.使用蓝图模块化程序

约定俗成:

创建blueprints目录用于存放各个蓝图,蓝图以包结构组织

image.png

1.创建蓝图

在每个蓝图包的init.py文件创建蓝图实例

1
2
3
4
5
6
7
8
python复制代码# @FileName: __init__.py

from flask import Blueprint
#从Flask导入Blueprint类,实例化这个类就获得了我们的蓝本对象。
user_bp = Blueprint("user",__name__)
#构造方法中的第一个参数是蓝本的名称;第二个参数是包或模块的名称,我们可以使用__name__变量
from . import login
#导入需要使用蓝图的视图文件,在下面导入解决循环导入报错

在蓝本对象的名称后添加一个_bp后缀.是为了更容易区分蓝本对象

2.注册蓝图

为了让蓝图发挥作用,我们需要把蓝本注册到程序实例上:

工厂函数中注册蓝图

image.png

3.使用蓝图

1
2
3
4
5
6
7
python复制代码//blueprints/user/login.py
from bluprints.user import user_bp


@user_bp.route('/')
def test():
return "hello bluprint"

五.构建NOSQL数据库连接模块

约定俗成:

项目根目录中(app.py同级)创建nosql数据库连接文件nosql_connection.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ini复制代码from pymongo import MongoClient
import redis
MONGODB_HOST = "106.14.107.75"
MONGODB_PORT = 27017
MONGODB_DATABASE = "mymongo"
REDIS_HOST = "106.14.107.75"
REDIS_PORT = 6379
REDIS_AUTH = "123456"

#mongodb 获取指定集合对象
def mongodbConnection(collectionName):
myclient = MongoClient(MONGODB_HOST, MONGODB_PORT)
mydb = myclient[MONGODB_DATABASE]
collection = mydb[collectionName]
return collection

#redis 获取指定数据库(0~15)连接对象
def redisConnection(databaseNum):
pool = redis.ConnectionPool(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_AUTH, db=databaseNum, decode_responses=True)
mycon = redis.Redis(connection_pool=pool)
return mycon

使用:

调用数据库连接方法,并传入相应参数,获取连接对象

1
2
3
4
ini复制代码collection = mongodbConnection("address")
#获得mongodb address集合操作对象
con = redisConnection(0)
#获得redis 0号数据库操作对象

六.集中式管理模型类

约定俗成:

项目根目录中(app.py同级)创建模型文件models.py

1
2
3
4
5
6
7
8
9
10
11
12
13
ini复制代码# @FileName: models
from extendsions import db


class User(db.Model):
__tablename__ = "user_flask"
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(20))
age = db.Column(db.Integer)
sex = db.Column(db.String(2))
love = db.Column(db.String(20))

#.......

模型迁移

将模型类导入app.py(重要),只需导入

image.png

七.模块化静态文件和模板文件

约定俗成:

以蓝图模块划分,各个蓝图拥有各自的静态文件与模板

image.png

完整项目结构

image.png

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%