多文件Flask程序 标准结构

|-flasky

    |-app/ 2.程序包

        |-templates/

        |-static/

        |-main/

            |-__init__.py

            |-errors.py

            |-foms.py

            |-views.py

         |-__init__.py

         |-email.py

         |-models.py

     |-migrations/

     |-tests/

         |-__init__.py

     |-venv/

     |-requirements.txt

     |-config.py  1.配置选项

     |-manage.py


  1. 配置选项


config.py 代码如下

import os \\ 导入 os模块

basedir = os.path.abspath(os.path.dirname(__file__))   \\设置 db生成 路径

class Config:   \\建立 Config 类    
    
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'      

    SQLALCHEMY_COMMIT_ON_TEARDOWN = True \\ 每次request自动提交db.session.commit(),
如果有一天你发现别的写的视图中有db.session.add,但没有db.session.commit,不要疑惑,他肯定配置了上面
的选项。这是通过app.teardown_appcontext注册实现
    
    MAIL_SERVER = 'smtp.googlemail.com'    
    MAIL_PORT = 587    
    MAIL_USE_TLS = True    
    MAIL_USERNAME = os.environ.get('MAIL_USERNAME')    
    MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')    
    FLASKY_MAIL_SUBJECT_PREFIX = '[Flasky]'    
    FLASKY_MAIL_SENDER = 'Flasky Admin <flasky@example.com>'    
    FLASKY_ADMIN = os.environ.get('FLASKY_ADMIN')    
        @staticmethod    
            def init_app(app):        
                pass
                
class DevelopmentConfig(Config):    
    DEBUG = True    
    SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \        
    'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')

class TestingConfig(Config):    
    TESTING = True    
    SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \        
    'sqlite:///' + os.path.join(basedir, 'data-test.sqlite')

class ProductionConfig(Config):    
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \        
    'sqlite:///' + os.path.join(basedir, 'data.sqlite')

config = {    'development': DevelopmentConfig,    
              'testing': TestingConfig,  
              'production': ProductionConfig,    
              'default': DevelopmentConfig
              }


Flask 应用加载Flask-SqlAlchemy扩展

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
 
app = Flask(__name__) 这一步在 app/__init__.py 实现
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:tmp/test.db' 这一步在config.py 实现
db = SQLAlchemy(app) 这个就是你以后操作数据库的对象实例了 这一步在 app/__init__.py 实现


2.程序包

 |-app/

        |-templates/

        |-static/

        |-main/

            |-__init__.py

            |-errors.py

            |-foms.py

            |-views.py

         |-__init__.py

         |-email.py

         |-models.py


(1)models.py 代码如下

from . import db  \\在数据库模型文件导入 同级目录下 __init__.py 中建立的db对象

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    users = db.relationship('User', backref='role', lazy='dynamic')
    def __repr__(self):
        return '<Role %r>' % self.name

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
    def __repr__(self):
        return '<User %r>' % self.username


(2)__init__.py 代码如下

from flask import Flask

#导入扩展模块
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() //创建 bootstrap 对象,实例化
mail = Mail()           //创建 mail 对象,实例化
moment = Moment()       //创建 moment 对象,实例化
db = SQLAlchemy()       //创建 db 对象,实例化

def create_app(config_name): //工厂函数 接收一个参数,是程序使用的配置名,在config.py中定义 
    app = Flask(__name__)
    app.config.from_object(config[config_name]) //通过Flask app.config 配置对象\
                                                提供的from_object()方法直接导入程序 
    
    config[config_name].init_app(app)
    
    #通过创建的扩展对象上调用init_app()可以完成初始化过程
    bootstrap.init_app(app) 
    mail.init_app(app)
    moment.init_app(app)
    db.init_app(app)
    
    # 附加路由和自定义错误页面
    from .main import main as main_blueprint  //导入蓝本
    app.register_blueprint(main_blueprint)    //对蓝本进行登记注册
    
    return app
    
 "bootstrap = Bootstrap()
  bootstrap.init_app(app)" 等效于 "bootstrap = Bootstrap(app)"

(3)main/__init__.py 代码如下

from flask import Blueprint

main = Blueprint('main', __name__) //实例化一个Buleprint类创建蓝本(蓝本名,蓝本所在的包)

from . import views, errors //在同级目录下 导入路由和错误处理程序


(4)main/views.py 代码如下

from flask import render_template, session, redirect, url_for, current_app
from .. import db //导入 上级目录下 __init__.py 中建立的main对象
from ..models import User //导入 上级目录下 models.py 中的User类
from ..email import send_email 
from . import main //导入 同级目录下 __init__.py 中建立的main对象
from .forms import NameForm //导入 同级目录下 form.py 中的NameForm类

@main.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.name.data).first()
        if user is None:
            user = User(username=form.name.data)
            db.session.add(user)
            session['known'] = False
            if current_app.config['FLASKY_ADMIN']:
                send_email(current_app.config['FLASKY_ADMIN'], 'New User',
                           'mail/new_user', user=user)
        else:
            session['known'] = True
        session['name'] = form.name.data
        return redirect(url_for('.index'))
    return render_template('index.html',
                           form=form, name=session.get('name'),
                           known=session.get('known', False))

(4)main/form.py 代码如下

from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required

class NameForm(Form):
    name = StringField('What is your name?', validators=[Required()])
    submit = SubmitField('Submit')

(5)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

3.启动脚本

manage.py 代码如下:

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)

@manager.command
def test():
    """Run the unit tests."""
    import unittest
    tests = unittest.TestLoader().discover('tests')
    unittest.TextTestRunner(verbosity=2).run(tests)

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