学习flask-7-项目结构

flask大型项目结构

把程序模块化。
最终结构:

|-flasky
    |-app/
        |-templates/
        |-static/
        |-main/
            |-__init__.py
            |-errors.py
            |-forms.py
            |-views.py
        |-__init__.py
        |-email.py
        |-models.py
    |-migrations/
    |-tests/
        |-__init__.py
        |-test*.py
    |-venv/
    |-requirements.txt
    |-config.py
    |-manage.py
  • 程序在app中。
  • config.py存储设置
  • manage.py启动程序

7.2 配置选项

开发,测试,生产使用不同的数据库.
放在根目录config.py

7.3 程序文件夹

程序代码分门别类放在app/下,templates和static也放在下面
数据库和电子邮件支持放在app/models.py 和 app/email.py。

7.3.1 application factory 工厂函数

单个文件程序一旦运行起来就无法再对程序进行修改了,也就是不能在程序运行的时候动态修改配置。

为了能动态修改配置(程序运行时候),需要延迟创建程序实例,把创建过程移到可显式调用的工厂函数中。这种方法不仅可以给脚本留出配置程序的时间,还能够创建多个程序实例,这些实例有时在测试中非常有用。程序的工厂函数在 app 包的构造文件中定义.

这些是flask框架提供的:

  • config配置对象提供的下面两个方法
  • from_object导入config中的配置类
  • init_app初始化

构造文件:app/init.py

from flask import Flask, render_template
from flask.ext.bootstrap import Bootstrap
from flask.ext.mail import Mail
from flask.ext.moment import Moment
from flask.ext.sqlalchemy import SQLAlchemy
from config import config
bootstrap = Bootstrap()
mail = Mail()
moment = Moment()
db = SQLAlchemy()

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)

    bootstrap.init_app(app)
    mail.init_app(app)
    moment.init_app(app)
    db.init_app(app)

    # 附加路由和自定义的错误页面(见下节)

    return app

7.3.2 蓝本blueprint定义路由

在蓝本中定义的路由处于休眠状态,直到蓝本init到程序上后,路由才真正成为程序的一部分。和程序一样,蓝本可以在单个文件中定义,也可使用更结构化的方式在包中的多个模块中创建。为了获得最大的灵活性,程序包中创建了一个子包,用于保存蓝本。

app/main/init.py :创建蓝本

from flask import Blueprint
main = Blueprint('main', __name__)
from . import views, errors

‘main’, name: 蓝本的名字main和蓝本所在的包或模块.

app/init.py中加入:

# 附加路由和自定义的错误页面
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)

程序的路由保存在包里的 app/main/views.py 模块中,而错误处理程序保存在 app/main/errors.py 模块中。导入这两个模块就能把路由和错误处理程序与蓝本关联起来。注意,这些模块在app/main/init.py 脚本的末尾导入,这是为了避免循环导入依赖,因为在views.py 和 errors.py 中还要导入蓝本 main 。

app/main/errors.py:

from flask import render_template
from . import main

@main.app_errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

@main.app_errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500

如果使用 errorhandler 修饰器,那么只有蓝本中的错误才能触发处理程序。要想注册程序全局的错误处理程序,必须使用 app_errorhandler 。

蓝本中的视图函数:

app/main/views.py: 蓝本中定义的程序路由
from datetime import datetime
from flask import render_template, session, redirect, url_for
from . import main
from .forms import NameForm
from .. import db
from ..models import User
@main.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        # ...
        return redirect(url_for('.index'))
    return render_template('index.html',
        form=form, name=session.get('name'),
        known=session.get('known', False),
        current_time=datetime.utcnow())

不同之处:

  • 路由修饰器由蓝本提供
  • url_for() 函数的用法不同:

    你可能还记得, url_for() 函数的第一个参数是路由的端点名, 在程序的路由中,默认为视图函数的名字。例如,在单脚本程序中, index() 视图函数的 URL 可使用 url_for(‘index’) 获取。
    在蓝本中就不一样了, Flask 会为蓝本中的全部端点加上一个命名空间,这样就可以在不同的蓝本中使用相同的端点名定义视图函数, 而不会产生冲突。命名空间就是蓝本的名字( Blueprint 构造函数的第一个参数),所以视图函数 index() 注册的端点名是 main.index,其 URL 使用url_for(‘main.index’) 获取。
    简写为.index就是当前请求所在的蓝本。

表单对象也要放到蓝本中,app/main/forms.py

7.4 启动脚本

根目录下的manage.py文件用于启动程序

#!/usr/bin/env python
import os
from app import create_app, db
from app.models import User, Role
from flask.ext.script import Manager, Shell
from flask.ext.migrate import Migrate, MigrateCommand

app = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(app)
migrate = Migrate(app, db)

def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)
manager.add_command("shell", Shell(make_context=make_shell_context))
manager.add_command('db', MigrateCommand)

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

第一行叫shebang声明。可以直接./manage.py

7.5 用到的包

生成requirements
(venv) $ pip freeze >requirements.txt

如果你要创建这个虚拟环境的完全副本,可以创建一个新的虚拟环境,并在其上运行以下
命令:

(venv) $ pip install -r requirements.txt

Flask==0.10.1
Flask-Bootstrap==3.0.3.1
Flask-Mail==0.9.0
Flask-Migrate==1.1.0
Flask-Moment==0.2.0
Flask-SQLAlchemy==1.0
Flask-Script==0.6.6
Flask-WTF==0.9.4
Jinja2==2.7.1
Mako==0.9.1
MarkupSafe==0.18
SQLAlchemy==0.8.4
WTForms==1.0.5
Werkzeug==0.9.4
alembic==0.6.2
blinker==1.3
itsdangerous==0.23

7.6 单元测试

执行 git checkout 7a 签出程序的这个版本。为确保安装了所有依赖包,还需执行 pip install -r requirements.txt 命令.
/tests/test_basics.py

import unittest #for python test
from flask import current_app
from app import create_app, db

class BasicsTestCase(unittest.TestCase):
    def setUp(self):
        self.app = create_app('testing')
        self.app_context = self.app.app_context()
        self.app_context.push()
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()
        self.app_context.pop()

    def test_app_exists(self):
        self.assertFalse(current_app is None)

    def test_app_is_testing(self):
        self.assertTrue(current_app.config['TESTING'])

在manage.py中设置了命令行运行单元测试

7.7 创建数据库

如果使用 Flask-Migrate 跟踪迁移,可使用如下命令创建数据表或者升级到最新修订版本:

(venv) $ python manage.py db upgrade

设置环境变量

查看:
$ export

/manage.py中os.getenv(‘FLASK_CONFIG’)
/config.py中os.environ.get()