| -flasky
| -app/
|-init.py
|-email.py
|-models.py
|-templates/
|-statics/
|-main/
|-init.py
|-errors.py
|-forms.py
|-views.py
|-migrations/
|-tests/
|-init.py
|-test*.py
|-venv/
|-requirements.txt
|-config.py
|-flasky.py
有四个顶级目录:
Flask应用保存在app包中;
数据库迁移脚本在migrations文件夹中;
单元测试在tests包中编写;
虚拟环境在venv文件夹中。
requirement.txt列出所有依赖包
config.py存储配置
flask.py定义Flask应用实例,同时还有一些辅助管理应用的任务。
config.py
config.py中设置一些参数,建议把邮箱敏感信息配置到系统参数内
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'
MAIL_SERVER = os.environ.get('MAIL_SERVER', 'smtp.googlemail.com')
MAIL_PORT = int(os.environ.get('MAIL_PORT', '587'))
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS', 'true').lower() in \
['true', 'on', '1']
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')
SQLALCHEMY_TRACK_MODIFICATIONS = False
@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://'
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
}
应用
在app/init.py中,使用工厂函数
from flask import Flask, render_template
from flask_bootstrap import Bootstrap from flask_mail import Mail
from flask_moment import Moment
from flask_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
在app/main/init.py中,书上是这么写的,在末尾引入views和errors说是为了避免循环导入依赖
from flask import Blueprint
main = Blueprint('main', __name__)
from . import views, errors
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
flasy.py
其中@app.shell_context_processor装饰器,会创建并注册一个shell上下文处理器
调用flask的shell时,可以设置环境变量FLASK_APP=flasky.py
import os
from app import create_app, db
from app.models import User, Role
from flask_migrate import Migrate
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
migrate = Migrate(app, db)
@app.shell_context_processor
def make_shell_context():
return dict(db=db, User=User, Role=Role)
依赖文件
创建当前依赖文件:
pip freeze>requirements.txt
安装requirements.txt中的依赖
pip install -r requirements.txt
七月老师的目录树结构是这样的:
app
app.py
config
secure.py
setting.py
project_name.py
在app.py中设置一个create_app,和一个register_blueprint,在create_app中调用register_blueprint把蓝图注册到app中,然后引用config文件下的配置文件,project_name.py从app生成一个app,然后启动。