规范结构维护代码

    很显然,作为有洁癖的工程师,肯定不能容忍所有代码都这么一团塞在一个文件里面的,所以我们至少会想到拆分代码然后放到几个模块里面,例如什么 model.py, controller.py 啊之类的。但是,作为有深度洁癖的人,觉得把一大堆文件放在一个目录里面也是件糟心的事,所以,这里我要介绍一下我比较推荐的代码目录结构。

    虽然目录结构见仁见智,个人有个人的看法和习惯,但总的来说,经过很多人的实践和总结,还是有很多共同的意见和想法的,而我在查看他人的目录结构结合自身在工作中的使用经验,总结了一个个人认为比较恰当的目录结构供参考,而本书也是以这个目录结构为架构进行下去的。

    我推荐的目录结构:

    • application:项目所有逻辑代码都放这
    • config:项目的配置文件,按不同环境各占一份
    • deploy:部署相关的文件,后续将使用到
    • tests:单元测试代码所在的目录

    文件的话分别有:

    • manage.py:Flask-Script 运行文件,后面介绍
    • pylintrc:静态分析代码使用的 pylint 标准
    • requirements.txt:项目依赖库的列表
    • wsgi.py:wsgi 运行的文件

    既然我们已经规定好了目录结构,是时候将我们的意面分到各个盘子里了。首先从文件开始,因为我们还没有介绍 Flask-Script,静态检查和 wsgi,所以就忽略这些文件,那么就剩下 requirements.txt 文件了。这个文件的内容都在我们的 《本书概述》中列举了,直接放进去就好了。

    1. Flask==0.10.1
    2. flask-mongoengine==0.7.5
    3. Flask-Login==0.3.2
    4. Flask-Admin==1.4.0
    5. Flask-Redis==0.1.0
    6. Flask-WTF==0.12

    然后是时候解耦代码了,我们没有表单,暂时没有 services,没有静态文件也没有页面模板,所以可以这样合并:

    • 将 route 代码放到 application/controllers 中
    • 将 model 代码放到 application/models 中
    • 将初始化绑定 app 的代码放到 application/init.py 中
    • 将 数据库等配置放到 config/development.py 中

    manager.py

    application/init.py

    1. # coding: utf-8
    2. import sys
    3. import os
    4. # Insert project root path to sys.path
    5. project_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
    6. if project_path not in sys.path:
    7. sys.path.insert(0, project_path)
    8. import logging
    9. from flask import Flask
    10. from flask_wtf.csrf import CsrfProtect
    11. from config import load_config
    12. from application.extensions import db, login_manager
    13. from application.models import User
    14. # convert python's encoding to utf8
    15. try:
    16. reload(sys)
    17. sys.setdefaultencoding('utf8')
    18. except (AttributeError, NameError):
    19. pass
    20. """Create Flask app."""
    21. config = load_config()
    22. print config
    23. app = Flask(__name__)
    24. app.config.from_object(config)
    25. if not hasattr(app, 'production'):
    26. app.production = not app.debug and not app.testing
    27. # CSRF protect
    28. CsrfProtect(app)
    29. if app.debug or app.testing:
    30. # Log errors to stderr in production mode
    31. app.logger.addHandler(logging.StreamHandler())
    32. app.logger.setLevel(logging.ERROR)
    33. # Register components
    34. register_extensions(app)
    35. register_blueprint(app)
    36. return app
    37. def register_extensions(app):
    38. db.init_app(app)
    39. login_manager.init_app(app)
    40. login_manager.login_view = 'login'
    41. @login_manager.user_loader
    42. def load_user(user_id):
    43. return User.objects(id=user_id).first()
    44. def register_blueprint(app):
    45. app.register_blueprint(user_bp)

    application/controllers/init.py

    1. # coding: utf-8
    2. import os
    3. class DevelopmentConfig(object):
    4. """Base config class."""
    5. # Flask app config
    6. DEBUG = False
    7. TESTING = False
    8. SECRET_KEY = "sample_key"
    9. # Root path of project
    10. PROJECT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
    11. # Site domain
    12. SITE_TITLE = "twtf"
    13. SITE_DOMAIN = "http://localhost:8080"
    14. # MongoEngine config
    15. MONGODB_SETTINGS = {
    16. 'db': 'the_way_to_flask',
    17. 'host': 'localhost',
    18. 'port': 27017
    19. }