概述
要想用Flask开发大型项目,就必须要有良好的项目文件结构,这篇文章主要记录Flask最小开发项目的配置。这里所使用的Python版本为3.5.1,Flask版本为0.11.1。
测试环境
- Python版本:3.5.1
- Flask版本:0.11.1
- PyCharm版本:5.0.3
主要目录
主要目录如下:
文件夹说明
app
app为放置应用程序的文件夹,主要有auth和models,auth是放置Flask的蓝本程序,models放置操作数据库的代码。
auth的__init__.py
主要是配置蓝本:
from flask import Blueprint
auth = Blueprint('auth', __name__)
app的__init__.py
app的__init__.py代码如下:
# coding=utf-8
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import config
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
db.init_app(app)
db.app = app
# 注册蓝本
# 增加auth蓝本
from app.auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth')
# 附加路由和自定义的错误页面
return app
tests
tests文件夹为测试文件夹,编写单元测试的代码放在这里。下面是一份单元测试的示例代码:
# test_basic.py
import unittest
from flask import current_app
from app import create_app, db
class BasicTestCase(unittest.TestCase):
"""
setUP()和tearDown()方法分别在各测试前后运行,
并且名字以test_开头的函数都作为测试执行。
"""
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'])
venv
venv是放置虚拟环境的私有包。
虚拟环境是Python解释器的一个私有副本,在这个环境中你可以安装私有包,并且不会影响系统中安装的全局Python解释器。
在PyCharm设置虚拟环境步骤:
点击右边那个设置按钮,会弹出下面一个弹窗,点击「Create VirtualEnv」后再设置「Local」和「Name」为当前工程目录的venv即可。
设置好虚拟环境后,可以开始下载所需的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'
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
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')
SQLALCHEMY_TRACK_MODIFICATIONS = True
class TestingConfig(Config):
TESTING = True
WTF_CSRF_ENABLED = False
SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'data-test.sqlite')
SQLALCHEMY_TRACK_MODIFICATIONS = True
class ProductionConfig(Config):
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'data.sqlite')
SQLALCHEMY_TRACK_MODIFICATIONS = True
config = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'prodection': ProductionConfig,
'default': DevelopmentConfig
}
manage.py
manage.py是Flask应用的启动脚本,用于启动程序,内容如下:
import os
from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager, Shell
from app import create_app, db
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)
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()
需求文件
程序中可以有一个requirements.txt文件,用于记录所有依赖包及其精确的版本号。
pip freeze > requirements.txt
安装或升级包后,一定要更新这个文件。
当需要导入,安装各种包时:
pip install -r requirements.txt
其他
下面内容是返回JSON格式的接口设计示例,以及添加数据库接口和ORM。返回Json数据可以使用jsonify
。
auth/users.py内容如下:
from flask import request, jsonify
from app.models import *
from app.auth import auth
@auth.route('/apidemo', methods=['GET', 'POST'])
def apidemo():
"""一个返回JSON数据接口的设计示例"""
jsonResponse = dict(errCode="1", errMsg="操作成功!")
response = jsonify(jsonResponse)
return response
另外要在auth/__init__.py最后加上from .users import *
from flask import Blueprint
auth = Blueprint('auth', __name__)
from .users import *
models/users.py内容如下:
from app import db
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
UserCode = db.Column(db.String(64), unique=True, index=True)
Password = db.Column(db.String(128))
def __init__(self, UserCode=None, Password=None):
self.UserCode = UserCode
self.Password = Password
def __repr__(self):
return '<User %r>' % self.UserName