python flask源码 后端能做大型网站吗

flask web开发笔记 -- 大型应用结构 - 推酷
flask web开发笔记 -- 大型应用结构
Flask相当灵活,对如何组织大型项目没有要求。本节推荐一种组织方式
目录结构:
$ ls -R flasky
data.sqlite
migrations
requirements.txt
flasky/app:
__init__.py
flasky/app/main:
__init__.py
flasky/app/static:
favicon.ico
flasky/app/templates:
index.html
flasky/app/templates/mail:
new_user.html
new_user.txt
flasky/migrations:
alembic.ini
script.py.mako
flasky/migrations/versions:
46598b0f7f81_initial_migration.py
46598b0f7f81_initial_migration.pyc
flasky/tests:
__init__.py
test_basics.py
层次结构:
|-templates/
|-__init__.py
|-errors.py
|-forms.py
|-views.py
|-__init__.py
|-email.py
|-models.py
|-migrations/
|-__init__.py
|-test*.py
|-requirements.txt
|-config.py
|-manage.py
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
MAIL_SERVER = ''
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_ADMIN = os.environ.get('FLASKY_ADMIN')
@staticmethod
def init_app(app):
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
包含内容:email.py
.py main models.py static templates。
应用工厂函数
.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()
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)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
应用功能蓝图
app/main/__init__.py
注意在app/
.py中创建应用时,蓝图应最后导入,以避免循环导入。
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
视图app/main/views.py:
from flask import render_template, session, redirect, url_for, current_app
from .. import db
from ..models import User
from ..email import send_email
from . import main
from .forms import 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)
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))
#!/usr/bin/env python
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)
def test():
&&&Run the unit tests.&&&
import unittest
tests = unittest.TestLoader().discover('tests')
unittest.TextTestRunner(verbosity=2).run(tests)
if __name__ == '__main__':
manager.run()
这个文件可以通过pip freeze &requirements.txt自动生成。
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.1
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
可以通过pip install -r requirements.txt进行安装。
tests/test_basics.py
import unittest
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'])
执行结果:
$ python manage.py test
test_app_exists (test_basics.BasicsTestCase) ... ok
test_app_is_testing (test_basics.BasicsTestCase) ... ok
.----------------------------------------------------------------------
Ran 2 tests in 0.001s
数据库配置
各个环境的配置不同的环境变量,升级:python manage.py db upgrade。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致1222人阅读
Falsk开发(1)
Flask的大型网站模板
第一次学习使用Flask的时候是为了赶鸭子上架,那时候python和flask的优势就出来了,没有任何网站开发经验,两天部署出一个简单的微信公众平台,说到底这都是开源的力量,开源让我们处处有免费的代码使用,甚至可以进行二次开发。一个流行的开源软件,势必会银乐公众的瞩目,然后经过社区或者开发人员的验证,我们可以非常放心的使用,不过那次开发仅仅使用flask的路由功能,然会数据都是通过make_response函数来手动构造的,随后潜心学习了Falsk,从《FlaskWeb开发:基于Python的Web应用开发实战》一书中,收货很多,坐着丰富的开发经验,给Pythoner和Flask爱好者带来了盛宴。
好了废话已经很多了,现在该正题了。Flask是Python中很流行的Web后端框架,其受欢迎度不输于Django,Flask是一个使用 Python 编写的轻量级 Web 应用框架。有些人喜欢叫Flask是微框架,下面给出一些解释:
“微”并不代表整个应用只能塞在一个 Python 文件内,当然塞在单一文件内也是可以的。 “微”也不代表 Flask 功能不强。微框架中的“微”字表示 Flask 的目标是保持核心既简 单而又可扩展。 Flask 不会替你做出许多决定,比如选用何种数据库。类似的决定,如 使用何种模板引擎,是非常容易改变的。 Flask 可以变成你任何想要的东西,一切恰到 好处,由你做主。
所以Flask相当小型,而且开发起来也很顺手。现在,如果要使用Flask进行大型网站开发,怎么办?Flask其实提供了开发网站的方式,我们可以从程序结构上来入手。让我们慢慢进入主题。
一、Flask的Web引擎
对Web或者TCP/IP有所研究的人,都对HTTP不陌生吧,HTTP其实是一个非常简单的协议,运行在可靠的TCP层,然后通过四种方法来对服务器资源进行控制,当然现代的Web应用,让HTTP支持更多特性,必须长连接什么的~
在Python中有WSGI(Web Server Gateway Interface)来定制一个Web应用应该如何响应客户端的HTTP请求,在Flask,以来两大底层库,Werkzeug作为WSGI的工具箱,还有一个Jinja2的模板引擎。他们已经被深度集成在Flask中,在开发时,路由和响应使用了Werkzeug,render_temolate函数应用了Jinja2。
二、Flask的MVC影子
我不能断言Flask是依照MVC设计的,但是确实可以进行类似MVC的程序设计,这也是第一部分为什么非要说明Python的底层库,MVC互联网上有更专业的说明。
MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式:
Model(模型)表示应用程序核心(比如数据库记录列表)。
View(视图)显示数据(数据库记录)。
Controller(控制器)处理输入(写入数据库记录)。
MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
  通常模型对象负责在数据库中存取数据。
View(视图)是应用程序中处理数据显示的部分。
  通常视图是依据模型数据创建的。
Controller(控制器)是应用程序中处理用户交互的部分。
  通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
对于Flask来说,可以进行如下对照:
- Flask的路由功能,属于MVC的Controller,控制请求的响应方法;
- 对于路由覆盖的函数,就是MVC的View,处理请求,并返回需要渲染的html;
- 而类似的SQLalcehmy,就是MVC的Model,利用ORM或者预封装的数据模型,来控制数据的修改和更新。
当然,对于Flask来说,或者说现代的Web架构来说,这里面有许多边界模糊的地方,但是我们可以根据MVC模型指引,来引出对Flask的结构化开发,来达到软件的耦合度降低,减小软件维护难度。
需要说明的是,Flask并没有提供ORM模型,需要使用别的开源程序,比如流行的SQLAlchemy,ORM可以让我们更注重数据模型的建立,并建立数据绑定行为,来降低Model模型的耦合度。
三、大型网站的程序结构
有了前几部分的铺垫,我们现在可以说明基于Flask的Web程序结构了,让我们先一睹为快:
|-templates/
|-__init__.py
|-forms.py
|-views.py
|-__init__.py
|-errors.py
|-views.py
|-models.py
|-__init__.py
|-requirements.txt
|-config.py
|-manage.py
让我们基本介绍一下各文件的作用:
* manage.py
该脚本是开发者与程序的交互入口,比如启动Web程序,调试数据库,运行自定义命令等等
* config.py
该脚本是Web的配置文件,基本包括了该Web应用需要的配置信息,比如某些常数配置,或者环境变量(通常是处于保护隐私),数据库配置等等
* requirements.txt
该文件由pip自动生成,是本应用的python环境依赖包及其版本。
* app文件夹
app文件夹是本Web程序的主要功能设计部分,包括了路由路径设计,模板文件,静态文件和模型设计。
由于app部分的重要性,我们继续展开讲。
1. 模板与静态文件
模板就是服务器传给客户端的视图部分,可以通过Jinja2的模板引擎吧需要的内容,渲染到模板中,然后通过网络呈现给用户。
静态文件是网页所以来的css样式、js脚本、图标等部分,这一部分可以在部署生产环境的时候,交给反向代理器去做,减小Web后端的负担。
2. 数据库模型设计
数据库模型一般由ORM方式设计,然后提高程序的可用性。
3. 功能设计
在真实的设计场景中,会涉及多个功能,比如用户登录,博客文章,评论,用户管理等等。这时我们可以把他们分开设计,然后用上述文件结构进行功能性划分,每个功能文件夹中依照具体需求,可能会有不同的设计文件,但是肯定会有views视图文件的,这个是功能展示的基础。
好了这就是一个可以良好Web架构的程序结构了,欢迎大家拍砖。随后我会开源一个模板工程,同时会出更多的教程来讲解这个模板工程的功能,及其使用。谢谢大家捧场~~
我的个人Github主页:
一个开源的Flask博客系统:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:7571次
排名:千里之外请输入正确的邮箱
已有帐号请点击
帐号创建成功!
我们刚刚给你发送了一封验证邮件
请在48小时内查收邮件,并按照提示验证邮箱
感谢你对微口网的信任与支持
如果你没有收到邮件,请留意垃圾箱 或 重新发送
你输入的邮箱还未注册
还没有帐号请点击
你输入的邮箱还未注册
又想起来了?
邮件发送成功!
我们刚刚给你发送了一封邮件
请在5分钟内查收邮件,并按照提示重置密码
感谢你对微口网的信任与支持
如果你没有收到邮件,请留意垃圾箱 或 重新发送
对不起,你的帐号尚未验证
如果你没有收到邮件,请留意垃圾箱 或
意见与建议
请留下您的联系方式
* 留下您正确的联系方式,以便工作人员尽快与你取得联系
【实例开发】Flask框架构建大型Web应用程序的结构示例
虽然小型web应用程序用单个脚本可以很方便,但这种方法却不能很好地扩展。随着应用变得复杂,在单个大的源文件中处理会变得问题重重。与大多数其他web框架不同,Flask对大型项目没有特定的组织方式;应用程序的结构完全交给开发人员自己决定。在这一章,提出一个可能的方式来组织管理一个大型应用程序的包和模块。这种结构将用于书中其余的示例中。1、项目结构示例 基本多文件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这个结构有四个顶层目录:Flask应用一般放置在名为app的目录下。migrations目录包含数据库迁移脚本,这和之前说的一样。单元测试放置在test目录下venv目录包含Python虚拟环境,这和之前说的也是一样的。还有一些新的文件:requirements.txt列出一些依赖包,这样就可以很容易的在不同的计算机上部署一个相同的虚拟环境。config.py存储了一些配置设置。manage.py用于启动应用程序和其他应用程序任务。为了帮助你完全理解这个结构,下面会描述将hello.py应用改为符合这一结构的整个流程。2、配置选项应用程序通常需要几个配置设置。最好的例子就是在开发过程中需要使用不同的数据库,测试,生产环境,这样他们可以做到互不干扰。我们可以使用配置类的层次结构来代替hello.py中的简单类字典结构配置。下面展示了config.py文件。config.py:应用程序配置import osbasedir = 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_ADMIN = os.environ.get('FLASKY_ADMIN') &
&@staticmethod &def init_app(app):
& &passclass DevelopmentConfig(Config):
&DEBUG = True &MAIL_SERVER = '' &MAIL_PORT = 587 &MAIL_USE_TLS = True &MAIL_USERNAME = os.environ.get('MAIL_USERNAME') &MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
&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}Config基类包含一些相同配置;不同的子类定义不同的配置。额外配置可以在需要的时候在加入。为了让配置更灵活更安全,一些设置可以从环境变量中导入。例如,SECRET_KEY,由于它的敏感性,可以在环境中设置,但如果环境中没有定义就必须提供一个默认值。在三个配置中SQLALCHEMY_DATABASE_URI变量可以分配不同的值。这样应用程序可以在不同的配置下运行,每个可以使用不同的数据库。配置类可以定义一个将应用程序实例作为参数的init_app()静态方法。这里特定于配置的初始化是可以执行的。这里Config基类实现一个空init_app()方法。在配置脚本的底部,这些不同的配置是注册在配置字典中。将其中一个配置(开发配置)注册为默认配置。3、应用程序包应用程序包放置了所有应用程序代码、模板和静态文件。它被简单的称为app,也可以给定一个特定于应用的名称(如果需要的话)。templates和static目录是应用的一部分,因此这两个目录应该放置在app中。数据库模型和电子邮件支持功能也要置入到这个包中,每个都以app/models.py和app/email.py形式存入自己的模块当中。3.1、使用一个应用程序工厂在单个文件中创建应用程序的方式非常方便,但是它有一个大缺点。因为应用程序创建在全局范围,没有办法动态的适应应用配置的更改:脚本运行时,应用程序实例已经创建,所以它已经来不及更改配置。对于单元测试这是特别重要的,因为有时需要在不同的配置下运行应用程序来获得更好的测试覆盖率。解决这一问题的方法就是将应用程序放入一个工厂函数中来延迟创建,这样就可以从脚本中显式的调用。这不仅给脚本充足的时间来设置配置,也能用于创建多个应用程序实例——一些在测试过程中非常有用的东西。被定义在app包的构造函数中的应用程序工厂函数会在示例7-3中展示。这个构造函数导入大部分当前需要使用的扩展,但因为没有应用程序实例初始化它们,它可以被创建但不初始化通过不传递参数给它们的构造函数。create_app()即应用程序工厂函数,需要传入用于应用程序的配置名。配置中的设置被保存在config.py中的一个类中,可以使用Flask的app.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 Mailfrom flask.ext.moment import Momentfrom flask.ext.sqlalchemy import SQLAlchemy from config import configbootstrap = 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) &# attach routes and custom error pages here &
&return app工厂函数返回创建的应用程序实例,但是请注意,在当前状态下使用工厂函数创建的应用程序是不完整的,因为它们没有路由和自定义错误页面处理程序。这是下一节的主题。3.2、在蓝图中实现应用程序的功能应用程序工厂的转化工作引出了路由的复杂化。在单脚本应用中,应用程序实例是全局的,所以可以很容易地使用app.route装饰器定义路由。但是现在应用程序在运行时创建,app.route装饰器只有在create_app()调用后才开始存在,这就太迟了。就像路由那样,这些通过app.errorhandler装饰器定义的自定义错误页面处理程序也存在同样的问题。幸运的是Flask使用蓝图来提供一个更好的解决方案。一个蓝图就类似于一个可以定义路由的应用程序。不同的是,和路由相关联的蓝图都在休眠状态,只有当蓝图在应用中被注册后,此时的路由才会成为它的一部分。使用定义在全局作用域下的蓝图,定义应用程序的路由就几乎可以和单脚本应用程序一样简单了。和应用程序一样,蓝图可以定义在一个文件或一个包中与多个模块一起创建更结构化的方式。为了追求最大的灵活性,可以在应用程序包中创建子包来持有蓝图。下面展示了创建蓝图的构造函数。app/main/ _init__.py:创建蓝图_from flask import Blueprintmain = Blueprint('main', __name__) from . import views, errors蓝图是通过实例化Blueprint类对象来创建的。这个类的构造函数接收两个参数:蓝图名和蓝图所在的模块或包的位置。与应用程序一样,在大多数情况下,对于第二个参数值使用Python的__name__变量是正确的。应用程序的路由都保存在app/main/views.py模块内部,而错误处理程序则保存在app/main/errors.py中。导入这些模块可以使路由、错误处理与蓝图相关联。重要的是要注意,在app/init.py脚本的底部导入模块要避免循环依赖,因为view.py和errors.py都需要导入main蓝图。蓝图和应用程序一样注册在create_app()工厂函数中,如下所示。示例 app/ _init__.py:蓝图注册_def create_app(config_name):&& # ...& from .main import main as main_blueprint&& app.register_blueprint(main_blueprint)& return app下面则展示了错误处理。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 datetimefrom flask import render_template, session, redirect, url_forfrom . import mainfrom .forms import NameForm from .. import dbfrom ..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()函数的使用。你可能会回想,该函数的第一个参数为路由节点名,它给基于应用程序的路由指定默认视图函数。例如,单脚本应用程序中的index()视图函数的URL可以通过url_for('index')来获得。不同的是Flask名称空间适用于来自蓝图的所有节点,这样多个蓝图可以使用相同节点定义视图函数而不会产生冲突。名称空间就是蓝图名(Blueprint构造函数中的第一个参数),所以index()视图函数注册为main.index且它的URL可以通过url_for('main.index')获得。在蓝图中,url_for()函数同样支持更短格式的节点,省略蓝图名,例如url_for('.index')。有了这个,就可以这样使用当前请求的蓝图了。这实际意味着相同蓝图内的重定向可以使用更短的形式,如果重定向跨蓝图则必须使用带名称空间的节点名。完成了应用程序页面更改,表单对象也保存在app/main/forms.py模块中的蓝图里面。4、启动脚本顶层目录中的manage.py文件用于启动应用。manage.py:启动脚本#!/usr/bin/env pythonimport osfrom app import create_app, dbfrom app.models import User, Rolefrom flask.ext.script import Manager, Shellfrom flask.ext.migrate import Migrate, MigrateCommandapp = 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()这个脚本开始于创建应用程序。使用环境变量FLASK_CONFIG,若它已经定义了则从中获取配置;如果没有,则是用默认配置。然后用于Python shell的Flask-Script、Flask-Migrate以及自定义上下文会被初始化。为了方便,会增加一行执行环境,这样在基于Unix的操作系统上可以通过./manage.py来执行脚本来替代冗长的python manage.py。5、需求文件应用程序必须包含requirements.txt文件来记录所有依赖包,包括精确的版本号。这很重要,因为可以在不同的机器上重新生成虚拟环境,例如在生产环境的机器上部署应用程序。这个文件可以通过下面的pip命令自动生成:1(venv) $ pip freeze &requirements.txt当安装或更新一个包之后最好再更新一下这个文件。以下展示了一个需求文件示例:Flask==0.10.1Flask-Bootstrap==3.0.3.1Flask-Mail==0.9.0Flask-Migrate==1.1.0Flask-Moment==0.2.0Flask-SQLAlchemy==1.0Flask-Script==0.6.6Flask-WTF==0.9.4Jinja2==2.7.1Mako==0.9.1MarkupSafe==0.18SQLAlchemy==0.8.4WTForms==1.0.5Werkzeug==0.9.4alembic==0.6.2blinker==1.3itsdangerous==0.23当你需要完美复制一个虚拟环境的时候,你可以运行以下命令创建一个新的虚拟环境:1(venv) $ pip install -r requirements.txt当你读到这时,示例requirements.txt文件中的版本号可能已经过时了。如果喜欢你可以尝试用最近发布的包。如果遇到任何问题,你可以随时回退到需求文件中与应用兼容的指定版本。6、单元测试这个应用非常小以至于不需要太多的测试,但是作为示例会在示例中展示两个简单的测试定义。示例:tests/test_basics.py:单元测试123456789101112131415161718192021import unittestfrom flask import current_app from app import create_app, dbclass 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'])编写好的测试使用的是来自于Python标准库中标准的unittest包。setUp()和tearDown()方法在每个测试之前和之后运行,且任何一个方法必须以test_开头作为测试来执行。建议:如果你想要学习更多使用Python的unittest包来写单元测试的内容,请参阅官方文档。setUp()方法尝试创建一个测试环境,类似于运行应用程序。首先它创建应用程序配置用于测试并激活上下文。这一步确保测试可以和常规请求一样访问current_app。然后,当需要的时候,可以创建一个供测试使用的全新数据库。数据库和应用程序上下文会在tearDown()方法中被移除。第一个测试确保应用程序实例存在。第二个测试确保应用程序在测试配置下运行。为了确保tests目录有效,需要在tests目录下增加__init__.py文件,不过该文件可以为空,这样unittest包可以扫描所有模块并定位测试。建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 7a来切换到这个版本的应用程序。为了确保你已经安装了所有依赖集,需要运行pip install -r requirements.txt。为了运行单元测试,可以在manage.py脚本中增加一个自定义的命令。下面展示如何添加测试命令。示例:manage.pyt:单元测试启动脚本123456@manager.commanddef test(): &&&&Run the unit tests.&&& &import unittest &tests = unittest.TestLoader().discover('tests')
&unittest.TextTestRunner(verbosity=2).run(tests)<mand装饰器使得它可以很容易的实现自定义命令。被装饰的函数名可以被当做命令名使用,且函数的文档字符串会显示帮助信息。test()函数的执行会调用unittest包中的测试运行器。单元测试可以像下面这样执行:1(venv) $ python manage.py test1234567test_app_exists (test_basics.BasicsTestCase) ... oktest_app_is_testing (test_basics.BasicsTestCase) ... ok.----------------------------------------------------------------------Ran 2 tests in 0.001sOK7、数据库启动与单脚本的应用相比,重构后的应用使用不同数据库。从环境变量中获取的数据库URL作为首选,默认SQLite数据库作为可选。三个配置中的环境变量和SQLite数据库文件名是不一样的。例如,开发配置的URL是从DEV_DATABASE_URL环境变量中获取,如果没有定义则会使用名为data-dev.sqlite的SQLite数据库。无论数据库URL源的是哪一个,都必须为新的数据库创建数据库表。如果使用了Flask-Migrate来保持迁移跟踪,数据库表可以被创建或更新到最近的版本通过下面的命令:1(venv) $ python manage.py db upgrade相信与否,已经到了第一部分结束的地方。你现在已经学到了Flask必要的基本要素,但是你不确定如何将这些零散的知识组合在一起形成一个真正的应用程序。第二部分的目的是通过开发一个完整的应用程序来带领你继续前行。
15人赞过此文
浏览器扫一扫
分享到朋友圈
社会化媒体
了解更多>>
桂ICP备 号-1
桂公网安备 36号
阅读下一篇
可扩充性可说是Python作为一种编程语言的特色。新的内置模块(module)可以用C 或 C++写成。而
Hi,看起来你很喜欢这些内容,但是你还没有登录!在你登录以后,就可以收藏感兴趣的内容,关注感兴趣的作者!

我要回帖

更多关于 flask和django的对比 的文章

 

随机推荐