规范结构维护代码
很显然,作为有洁癖的工程师,肯定不能容忍所有代码都这么一团塞在一个文件里面的,所以我们至少会想到拆分代码然后放到几个模块里面,例如什么 model.py, controller.py 啊之类的。但是,作为有深度洁癖的人,觉得把一大堆文件放在一个目录里面也是件糟心的事,所以,这里我要介绍一下我比较推荐的代码目录结构。
虽然目录结构见仁见智,个人有个人的看法和习惯,但总的来说,经过很多人的实践和总结,还是有很多共同的意见和想法的,而我在查看他人的目录结构结合自身在工作中的使用经验,总结了一个个人认为比较恰当的目录结构供参考,而本书也是以这个目录结构为架构进行下去的。
我推荐的目录结构:
- application:项目所有逻辑代码都放这
- config:项目的配置文件,按不同环境各占一份
- deploy:部署相关的文件,后续将使用到
- tests:单元测试代码所在的目录
文件的话分别有:
- manage.py:Flask-Script 运行文件,后面介绍
- pylintrc:静态分析代码使用的 pylint 标准
- requirements.txt:项目依赖库的列表
- wsgi.py:wsgi 运行的文件
既然我们已经规定好了目录结构,是时候将我们的意面分到各个盘子里了。首先从文件开始,因为我们还没有介绍 Flask-Script,静态检查和 wsgi,所以就忽略这些文件,那么就剩下 requirements.txt 文件了。这个文件的内容都在我们的 《本书概述》中列举了,直接放进去就好了。
Flask==0.10.1
flask-mongoengine==0.7.5
Flask-Login==0.3.2
Flask-Admin==1.4.0
Flask-Redis==0.1.0
Flask-WTF==0.12
然后是时候解耦代码了,我们没有表单,暂时没有 services,没有静态文件也没有页面模板,所以可以这样合并:
- 将 route 代码放到 application/controllers 中
- 将 model 代码放到 application/models 中
- 将初始化绑定 app 的代码放到 application/init.py 中
- 将 数据库等配置放到 config/development.py 中
manager.py
application/init.py
# coding: utf-8
import sys
import os
# Insert project root path to sys.path
project_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if project_path not in sys.path:
sys.path.insert(0, project_path)
import logging
from flask import Flask
from flask_wtf.csrf import CsrfProtect
from config import load_config
from application.extensions import db, login_manager
from application.models import User
# convert python's encoding to utf8
try:
reload(sys)
sys.setdefaultencoding('utf8')
except (AttributeError, NameError):
pass
"""Create Flask app."""
config = load_config()
print config
app = Flask(__name__)
app.config.from_object(config)
if not hasattr(app, 'production'):
app.production = not app.debug and not app.testing
# CSRF protect
CsrfProtect(app)
if app.debug or app.testing:
# Log errors to stderr in production mode
app.logger.addHandler(logging.StreamHandler())
app.logger.setLevel(logging.ERROR)
# Register components
register_extensions(app)
register_blueprint(app)
return app
def register_extensions(app):
db.init_app(app)
login_manager.init_app(app)
login_manager.login_view = 'login'
@login_manager.user_loader
def load_user(user_id):
return User.objects(id=user_id).first()
def register_blueprint(app):
app.register_blueprint(user_bp)
application/controllers/init.py
# coding: utf-8
import os
class DevelopmentConfig(object):
"""Base config class."""
# Flask app config
DEBUG = False
TESTING = False
SECRET_KEY = "sample_key"
# Root path of project
PROJECT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
# Site domain
SITE_TITLE = "twtf"
SITE_DOMAIN = "http://localhost:8080"
# MongoEngine config
MONGODB_SETTINGS = {
'db': 'the_way_to_flask',
'host': 'localhost',
'port': 27017
}