生产环境下Flask项目目录构建
接触Flask已经有大半年了,本篇博客主要来探讨如何规范化生产环境下Flask的项目目录结构。虽然目录结构见仁见智,个人有个人的看法和习惯,但总的来说,经过很多人的实践和总结,还是有很多共同的意见和想法的,而我在查看他人的目录结构结合自身在工作中的使用经验,总结了一个个人认为比较恰当的目录结构供参考。
我推荐的目录结构:
.
├── README.md
├── application
│ ├── __init__.py
│ ├── controllers
│ │ └── __init__.py
│ ├── forms
│ │ └── __init__.py
│ ├── models
│ │ └── __init__.py
│ ├── services
│ │ └── __init__.py
│ ├── static
│ │ └── __init__.py
│ ├── templates
│ │ └── __init__.py
│ └── utils
│ └── __init__.py
├── config
│ ├── __init__.py
│ ├── default.py
│ ├── development.py
│ ├── development_sample.py
│ ├── production.py
│ ├── production_sample.py
│ └── testing.py
├── deploy
│ ├── flask_env.sh
│ ├── gunicorn.conf
│ ├── nginx.conf
│ └── supervisor.conf
├── manage.py
├── pylintrc
├── requirements.txt
├── tests
│ └── __init__.py
└── wsgi.py
这里稍作介绍,首先是第一级目录的话,主要分为两类,一类是目录,另一类是运行相关的文件;其中目录有:
- application:项目所有逻辑代码都放这
- config:项目的配置文件,按不同环境各占一份
- deploy:部署相关的文件,后续将使用到
- tests:单元测试代码所在的目录
文件的话分别有:
- manage.py:Flask-Script 运行文件,后面介绍
- pylintrc:静态分析代码使用的 pylint 标准
- requirements.txt:项目依赖库的列表
- wsgi.py:wsgi 运行的文件
规范代码到指定目录
既然我们已经规定好了目录结构,是时候将我们的意面分到各个盘子里了。首先从文件开始,因为我们还没有介绍 Flask-Script,静态检查和 wsgi,所以就忽略这些文件,那么就剩下 requirements.txt 文件了。
Flask==0.10.
flask-mongoengine==0.7.
Flask-Login==0.3.
Flask-Admin==1.4.
Flask-Redis==0.1.
Flask-WTF==0.12
然后是时候解耦代码了,我们没有表单,暂时没有 services,没有静态文件也没有页面模板,所以可以这样合并:
- 将 route 代码放到 application/controllers 中
- 将 model 代码放到 application/models 中
- 将初始化绑定 app 的代码放到 application/init.py 中
- 将 数据库等配置放到 config/development.py 中
最后就是编写 manager.py 文件了。这里概要得列举几个重要的文件,更多的文件大家可以从 github 上 clone 代码出来阅读。
合并后的文件manager.py:
# coding: utf-
from flask.ext.script import Manager
from application import create_app # Used by app debug & livereload
PORT = app = create_app()
manager = Manager(app) @manager.command
def run():
"""Run app."""
app.run(port=PORT) if __name__ == "__main__":
manager.run()
application/init.py:
# coding: utf-
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(, 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
from application.controllers import user_bp # convert python's encoding to utf8
try:
reload(sys)
sys.setdefaultencoding('utf8')
except (AttributeError, NameError):
pass def create_app():
"""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):
"""Register models."""
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:
#!/usr/bin/env python
# encoding: utf-
import json from flask import Blueprint, request, jsonify
from flask.ext.login import current_user, login_user, logout_user from application.models import User user_bp = Blueprint('user', __name__, url_prefix='') @user_bp.route('/login', methods=['POST'])
def login():
info = json.loads(request.data)
username = info.get('username', 'guest')
password = info.get('password', '') user = User.objects(name=username,
password=password).first()
if user:
login_user(user)
return jsonify(user.to_json())
else:
return jsonify({"status": ,
"reason": "Username or Password Error"}) @user_bp.route('/logout', methods=['POST'])
def logout():
logout_user()
return jsonify(**{'result': ,
'data': {'message': 'logout success'}}) @user_bp.route('/user_info', methods=['POST'])
def user_info():
if current_user.is_authenticated:
resp = {"result": ,
"data": current_user.to_json()}
else:
resp = {"result": ,
"data": {"message": "user no login"}}
return jsonify(**resp)
config/development.py:
# coding: utf-
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':
}
如果你有更好的项目目录结构,欢迎交流!要特别说明下,这篇博客之前就记录在我的印象笔记上,我是直接搬过来的,所以格式方面就很难看了!这得感谢同事黄俊,之前是没有写博客的习惯的,都是直接记录在印象笔记上!哈哈
生产环境下Flask项目目录构建的更多相关文章
- Python开发【项目】:生产环境下实时统计网站访问日志信息
日志实时分析系统 生产环境下有需求:要每搁五分钟统计下这段时间内的网站访问量.UV.独立IP等信息,用直观的数据表格表现出来 环境描述: 网站为Nginx服务,系统每日凌晨会对日志进行分割,拷贝到其他 ...
- Python开发程序:生产环境下实时统计网站访问日志信息
日志实时分析系统 生产环境下有需求:要每搁五分钟统计下这段时间内的网站访问量.UV.独立IP等信息,用直观的数据表格表现出来 环境描述: 网站为Nginx服务,系统每日凌晨会对日志进行分割,拷贝到其他 ...
- Mysql迁移工具在生产环境下的使用
在产品迭代开发发布过程中,由于业务需求的增加,数据库难免会有结构调整等操作. 在每个版本发布过程中怎么控制每个版本server端程序与数据库版本保持一致,以及数 据库升级.回滚等操作. 本博文宅鸟将向 ...
- [原]生产环境下的nginx.conf配置文件(多虚拟主机)
[原]生产环境下的nginx.conf配置文件(多虚拟主机) 2013-12-27阅读110 评论0 我的生产环境下的nginx.conf配置文件,做了虚拟主机设置的,大家可以根据需求更改,下载即可在 ...
- 一次生产环境下MongoDB备份还原数据
最近开发一个版本的功能当中用到了MongoDB分页,懒于造数据,于是就研究了下从生产环境上导出数据到本地来进行测试. 研究了一下,发现MongoDB的备份还原和MySQL语法还挺类似,下面请看详细介绍 ...
- 生产环境下lnmp的权限说明
https://www.cnblogs.com/zrp2013/p/4183546.html 有关权限说明:-rwxrw-r‐-1 root root 1213 Feb 2 09:39 50.html ...
- 生产环境下,oracle不同用户间的数据迁移。第三部分
任务名称:生产环境下schema ELON数据迁移至schema TIAN########################################前期准备:1:确认ELON用户下的对象状态se ...
- 总结:利用asp.net core日志进行生产环境下的错误排查(asp.net core version 2.2,用IIS做服务器)
概述 调试asp.net core程序时,在输出窗口中,在输出来源选择“调试”或“xxx-ASP.NET Core Web服务器”时,可以看到类似“info:Microsoft.AspNetCore. ...
- Java生产环境下性能监控与调优详解视频教程 百度云 网盘
集数合计:9章Java视频教程详情描述:A0193<Java生产环境下性能监控与调优详解视频教程>软件开发只是第一步,上线后的性能监控与调优才是更为重要的一步本课程将为你讲解如何在生产环境 ...
随机推荐
- AMD移动FP5平台时序解释
好文章推荐:https://wenku.baidu.com/view/199379576137ee06eef91828.html AMD(FP5封装)时序全解. 由于刚开始接触AMD移动平台,难免有错 ...
- 在Fedora24/25中轻松安装gcc 4.9
在Fedora24/25中轻松安装gcc 4.9 http://blog.csdn.net/u010158659/article/details/53608285 标签: gccgcc-4.9Fedo ...
- WPF3.5 使用BINDINGGROUP进行实体类和集合验证
前文介绍了自定义或系统自带的ValidationRule进行验证,这种方法对于单个元素的验证不错.很多时候,我们需要对表单(Form)进行验证,也就是对一个实体类进行验证,或者对一个集合的每项进行验证 ...
- LeetCode: Binary Tree Postorder Traversal [145]
[题目] Given a binary tree, return the postorder traversal of its nodes' values. For example: Given bi ...
- Cocos2d-x3.1FileUtilsTest使用
Cocos2d-x3.1中FileUtils的使用:本使用教程是基于HelloWorld的.仅仅需在HelloWorld的init()函数中加入例如以下代码 //头文件 #include " ...
- 九度OJ 1120:全排列 (DFS)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4471 解决:1139 题目描述: 给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列. 我们假设对于小写字母有'a' < ...
- Hibernate ManyToOne Mappings 多对一关联映射
Hibernate ManyToOne Mappings 多对一关联映射 Hibernate框架的使用步骤: 1.创建Hibernate的配置文件(hibernate.cfg.xml)2.创建持久化类 ...
- 7.JavaScript变量
VAR声明变量,一条语句可以声明多个变量 var name="Gates", age=56, job="CEO"; Value = undefined 在计算机 ...
- iOS 第三方登录之 QQ登录
一. 首先需要下载腾讯qq登录所需的库,下载地址是http://open.qq.com/ . 需要用到的有TencentOpenAPI.framework 和TencentOpenApi_IOS_Bu ...
- Android Weekly Notes Issue #243
Android Weekly Issue #243 February 5th, 2017 Android Weekly Issue #243 本期内容包括: ConstraintLayout的动画; ...