多文件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
配置选项
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 <[email protected]>' 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()