如何定义项目结构?
项目需要一个清晰的项目结构,按照不同的功能逻辑划分不同的功能模块
目录结构
project/
app/ # application
module1/ # 划分各个模块
module2/
...
log/ # 日志
.gitignore # 版本控制忽略文件
config.ini # 配置文件
README.md # README文档
requirements.txt or setup.py # 安装文件或者依赖文件
例如 Django 项目 django-admin startproject Project
python manage.py startapp app
Project/
app/ # app
mingrations/ # 数据库迁移记录
__init__.py
admin.py # 后台管理
apps.py # 定义app
models.py # 模型
tests.py # 测试
views.py # 视图
urls.py # 路由
project/ # 项目配置
__init__.py
asgi.py # ASGI配置。
settings.py # 系统配置
urls.py # 路由配置
wsgi.py # wsgi配置
manage.py # 进口文件、管理文件
再例如scrapy 项目 scrapy startproject Project
Project/
Project/ # app
spiders/ # 爬虫
__init__.py
items.py # 保存爬取数据的容器
middlewares.py # 下载中间件,爬虫中间件
pipelines.py # 数据清洗,存储,验证
settings.py # 全局配置
scrapy.cfg # 配置文件
以Flask 来举例,Flask 是个微型框架,扩展性比较强,但是它没有像Django 一样开始会帮你生成各模块的文件,需要我们自己去根据自己的需要去生成,那项目初始,怎么搭建一个复用性,扩展性比较强项目的结构呢?
可能原来我们的方式
import Flask
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
return 'Hello World'
if __name__ == '__main__':
app.run()
但是对于一个稍微大点的项目,把所有的模块都塞到一个文件里,明显是不行的。下边一步步的构建一个项目初始架构。
-
准备一个虚拟环境
python -m venv .venv
-
准备一些基础的文件,README.md 、.gitignore、config.ini、app文件夹 和进口文件等
Project/ app/ README.md .gitignore config.ini manage.py
-
Flask 核心,是
app = Flask(__name__)
的实例,项目中如果引入一些flask第三方插件都需要注册这个app,那我们可以用工厂方法去创建。在app里创建一个init.py文件#!/usr/bin/env python3 # -*- coding: utf-8 -*- from flask import Flask # import something def create_app(): app = Flask(__name__) # init app return app
-
在进口文件即启动文件 manage.py 中实例化app
from app import create_app app = create_app() if __name__ == '__main__': app.run()
-
以创建Blueprint 初始化注册app为例,介绍第三方或者内置的模块初始化app
-
在app里创建一个views文件夹,创建init.py 文件 和 user.py文件
user.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from flask import Blueprint user = Blueprint('user', __name__) @user.route('/login', methods=['GET', 'POST']) def login(): pass
init.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from .user import user login DEFAULE_BLUEPRINT = ( # 蓝本, 前缀 (user, '/api'), (login, '') ) def config_blueprint(app): for blueprint, url_prefix in DEFAULE_BLUEPRINT: app.register_blueprint(blueprint, url_prefix=url_prefix)
-
在app/init.py 中导入config_buleprint 方法
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from flask import Flask from app.views import config_blueprint def create_app(): app = Flask(__name__) # init app config_blueprint(app) return app
-
-
再以注册扩展为例介绍扩展如何添加到工厂方法里,例如要注册ORM中的数据库操作db实例
这里用到一个第三方库 flask_sqlalchemy 是对sqlclchemy的扩展
-
首先创建一个config.py 来定义app实例的配置
#!/usr/bin/env python3 # -*- coding: utf-8 -*- class Config: DEBUG = True JSON_AS_ASCII = False # 定义ORM映射的数据库连接URI SQLALCHEMY_DATABASE_URI = 'mysql+mysqlconnector://root:123456@127.0.0.1:3306/flask_db?charset=utf8' # 自动跟踪数据库 SQLALCHEMY_TRACK_MODIFICATIONS = True @staticmethod def init_app(app): pass
-
其次在app里创建一个models的文件夹,models里创建一个init.py 文件
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
-
在app里创建一个expansion.py 文件
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from app.models import db def config_expansion(app): db.init_app(app)
-
最后在create_app里注册,create_app 方法就变成了
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from flask import Flask from .config import Config from app.views import config_blueprint from app.expansion import config_expansion def create_app(): app = Flask(__name__) app.config.from_object(Config) # init app config_blueprint(app) config_expansion(app) return app
-
-
通常app文件夹里还需要一个settings.py 文件来定义配置一些全局变量
-
到目前为止,项目结构为
Project/ app/ # app models/ # 模型 __init__.py # 创建db views/ # 视图模块 __init__.py # config_blueprint user.py # user 视图蓝本 __init__.py # create_app config.py # app config expansion.py # 扩展 settings.py # 全局配置 .gitignore # 忽略文件 config.ini # 配置文件 manage.py # 进口文件 README.md # README.md
-
在最后生成依赖文件
pip freeze >requirements.txt
清晰的目录结构有助于开发人员更加快速便捷的开发,也可以使新加入的开发人员快速了解项目,当然想要完成一个较好的项目,除了项目架构外,还需要开发人员有一定的经验技术。
版本控制
团队协作离不开版本控制,每个项目都需要进行版本控制。
每个项目都需要一个版本号,最简单的做法是以 0.1.0 作为你的初始化开发版本,并在后续的每次发行时递增次版本号。
如何确定项目版本达到 1.0.0?
当你的软件被用于正式环境,它应该已经达到了 1.0.0 版。如果你已经有个稳定的 API 被使用者依赖,也会是 1.0.0 版。如果你很担心向下兼容的问题,也应该算是 1.0.0 版了。