Flask 学习 六 大型程序结构
pip freeze >requirement.txt 自动生成版本号
pip install -r requirement.txt 自动下载对应的库
梳理结构
config.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
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
# 邮件配置
MAIL_SERVER= 'smtp.qq.com'
MAIL_PORT = 465
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
}
app/__init__.py 使用程序工厂函数
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask
from flask_moment import Moment
from flask_bootstrap import Bootstrap
from flask_mail import Mail
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) # 附加使用蓝本路由和错误页面
from . import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
蓝本中实现路由和自定义错误页面
创建蓝本 app/main/__init__.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
main = Blueprint('main',__name__)
from . import views,errors
注册蓝本 app/__init__.py
# 附加使用蓝本路由和错误页面
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
app/main/error.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import render_template
from . import main #主程序的errorhandler
@main.errorhandler(404)
def page_not_find(e):
return render_template('404.html'), 404 @main.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'), 500
main/views.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import render_template,session,redirect,url_for,current_app
from . import main
from .forms import NameForm
from .. import db
from ..models import User
from ..email import send_mail # 使用蓝本自定义路由
@main.route('/', methods=['get', 'post'])
def index():
#name = None
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_mail(current_app.config['FLASKY_ADMIN'],'New user','mail/new_user',user=user)
else:
session['known'] = True
session['name']=form.name.data
form.name.data=''
return redirect(url_for('.index'))# 蓝本中index函数在main.index下
return render_template('index.html', name=session.get('name'), form=form, known=session.get('known',False))
main/forms.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired class NameForm(FlaskForm):
name = StringField('姓名', validators=[DataRequired()])
submit = SubmitField('提交')
app/email.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from threading import Thread
from flask import render_template,current_app
from . import mail
from flask_mail import Message
def send_async_email(app,msg):
with app.app_context():
mail.send(msg) def send_mail(to,subject,template,**kwargs):
app = current_app._get_current_object()
msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject,sender=app.config['FLASKY_MAIL_SENDER'],recipients=[to])
msg.body=render_template(template + '.txt',**kwargs)
msg.html = render_template(template + '.html', **kwargs)
thr = Thread(target=send_async_email,args=[app,msg])
thr.start()
return thr
app/models.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from app import 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
manage.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import os
from app import create_app,db
from app.models import User,Role
from flask_script import Manager,Shell
from flask_migrate import Migrate,MigrateCommand app=create_app(os.getenv('FLASK_CONFIG')or 'default')
manager = Manager(app)
# 数据库迁移
migrate = Migrate(app,db)
manager.add_command('db',MigrateCommand)
# 集成python shell
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.command
def test():
'''启动单元测试'''
import unittest
tests=unittest.TestLoader().discover('tests')
unittest.TextTestRunner(verbosity=2).run(tests) if __name__ == '__main__':
manager.run()
requirements.txt
alabaster==0.7.9
alembic==0.9.2
anaconda-client==1.6.0
anaconda-navigator==1.5
anaconda-project==0.4.1
astroid==1.4.9
astropy==1.3
attrs==16.3.0
Automat==0.5.0
Babel==2.3.4
backports.shutil-get-terminal-size==1.0.0
beautifulsoup4==4.5.3
bitarray==0.8.1
blaze==0.10.1
blinker==1.4
bokeh==0.12.4
boto==2.45.0
Bottleneck==1.2.0
cffi==1.9.1
chardet==2.3.0
chest==0.2.3
click==6.7
cloudpickle==0.2.2
clyent==1.2.2
colorama==0.3.7
comtypes==1.1.2
conda==4.3.16
configobj==5.0.6
constantly==15.1.0
contextlib2==0.5.4
cryptography==1.7.1
cssselect==1.0.1
cycler==0.10.0
Cython==0.25.2
cytoolz==0.8.2
dask==0.13.0
datashape==0.5.4
decorator==4.0.11
dill==0.2.5
Django==1.11
docutils==0.13.1
dominate==2.3.1
et-xmlfile==1.0.1
fastcache==1.0.2
Flask==0.12
Flask-Bootstrap==3.3.7.1
Flask-Cors==3.0.2
Flask-Mail==0.9.1
Flask-Migrate==2.0.3
Flask-Moment==0.5.1
Flask-Script==2.0.5
Flask-SQLAlchemy==2.2
Flask-WTF==0.14.2
get==0.0.0
gevent==1.2.1
greenlet==0.4.11
h5py==2.6.0
HeapDict==1.0.0
idna==2.2
imagesize==0.7.1
incremental==16.10.1
ipykernel==4.5.2
ipython==5.1.0
ipython-genutils==0.1.0
ipywidgets==5.2.2
isort==4.2.5
itsdangerous==0.24
jdcal==1.3
jedi==0.9.0
jieba==0.38
Jinja2==2.9.4
jsonschema==2.5.1
jupyter==1.0.0
jupyter-client==4.4.0
jupyter-console==5.0.0
jupyter-core==4.2.1
lazy-object-proxy==1.2.2
llvmlite==0.15.0
locket==0.2.0
lxml==3.7.2
Mako==1.0.6
MarkupSafe==0.23
matplotlib==2.0.0
menuinst==1.4.4
mistune==0.7.3
mpmath==0.19
multipledispatch==0.4.9
nbconvert==4.2.0
nbformat==4.2.0
networkx==1.11
nltk==3.2.2
nose==1.3.7
notebook==4.3.1
numba==0.30.1
numexpr==2.6.1
numpy==1.11.3
numpydoc==0.6.0
odo==0.5.0
olefile==0.44
openpyxl==2.4.1
pandas==0.19.2
parsel==1.1.0
partd==0.3.7
path.py==0.0.0
pathlib2==2.2.0
patsy==0.4.1
pep8==1.7.0
pickleshare==0.7.4
Pillow==4.0.0
ply==3.9
post==0.0.0
prompt-toolkit==1.0.9
psutil==5.0.1
public==0.0.0
py==1.4.32
pyasn1==0.1.9
pyasn1-modules==0.0.8
pycosat==0.6.1
pycparser==2.17
pycrypto==2.6.1
pycurl==7.43.0
PyDispatcher==2.0.5
pyflakes==1.5.0
Pygments==2.1.3
pylint==1.6.4
PyMySQL==0.7.11
pyOpenSSL==16.2.0
pyparsing==2.1.4
pytest==3.0.5
python-dateutil==2.6.0
python-editor==1.0.3
pytz==2016.10
pywin32==220
PyYAML==3.12
pyzmq==16.0.2
QtAwesome==0.4.3
qtconsole==4.2.1
QtPy==1.2.1
query-string==0.0.0
queuelib==1.4.2
request==0.0.0
requests==2.12.4
rope-py3k==0.9.4.post1
scikit-image==0.12.3
scikit-learn==0.18.1
scipy==0.18.1
Scrapy==1.3.3
seaborn==0.7.1
service-identity==16.0.0
setupfiles==0.0.0
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.10.0
snowballstemmer==1.2.1
sockjs-tornado==1.0.3
sphinx==1.5.1
spyder==3.1.2
SQLAlchemy==1.1.5
statsmodels==0.6.1
sympy==1.0
tables==3.2.2
toolz==0.8.2
tornado==4.4.2
traitlets==4.3.1
Twisted==17.1.0
unicodecsv==0.14.1
visitor==0.1.3
w3lib==1.17.0
wcwidth==0.1.7
Werkzeug==0.11.15
widgetsnbextension==1.2.6
win-unicode-console==0.5
wordcloud==1.3.1
wrapt==1.10.8
WTForms==2.1
xlrd==1.0.0
XlsxWriter==0.9.6
xlwings==0.10.2
xlwt==1.2.0
zope.interface==4.3.3
单元测试
test/test_basic.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import unittest
from flask import current_app
from app import create_app,db class BasicTestCase(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'])
单元测试注册到主程序manager.py
@manager.command
def test():
'''启动单元测试'''
import unittest
tests=unittest.TestLoader().discover('tests')
unittest.TextTestRunner(verbosity=2).run(tests)
1、创建数据库
python manage.py shell
from app import db
db.create_all()
2、创建数据库迁移
python hello.py db init # 创建 migrations 文件夹,所有迁移脚本都存放其中
3、创建迁移脚本
python manage.py db migrate
4、更新数据库
python manage.py db upgrade
Flask 学习 六 大型程序结构的更多相关文章
- Celery 与 Flask 大型程序结构的结合
:first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; m ...
- Python学习笔记(Ⅰ)——Python程序结构与基础语法
作为微软的粉丝,最后终于向Python低头了,拖了两三个月终于下定决心学习Python了.不过由于之前受到C/C#等语言影响的思维定式,前期有些东西理解起来还是很费了些功夫的. 零.先抄书: 1.Py ...
- flask学习(六):URL传参
1. 参数的作用:可以在相同的URL,但是指定不同的参数,来加载不同的数据 例如:简书上每一篇文章前面的URL相同,只是后面的参数不同 2. 在flask中如何使用参数: 注意: 1) 参数需要放在两 ...
- [ Python ] Flask 基于 Web开发 大型程序的结构实例解析
作为一个编程入门新手,Flask是我接触到的第一个Web框架.想要深入学习,就从<FlaskWeb开发:基于Python的Web应用开发实战>这本书入手,本书由于是翻译过来的中文版,理解起 ...
- c# 程序结构
最近工作中需要用到c#,所以从今天开始博客不定期更新c#学习笔记 c#程序结构大体分为, 命名空间 类 Main 方法 命名空间 相当于一个仓库 通过 using 引入命名空间 比如 using ...
- Flask从入门到精通之大型程序的结构一
尽管在单一脚本中编写小型Web 程序很方便,但这种方法并不能广泛使用.程序变复杂后,使用单个大型源码文件会导致很多问题.不同于大多数其他的Web 框架,Flask 并不强制要求大型项目使用特定的组织方 ...
- C++ Primer 学习笔记_88_用于大型程序的工具 --异常处理[续1]
用于大型程序的工具 --异常处理[续1] 四.又一次抛出 有可能单个catch不能全然处理一个异常.在进行了一些校正行动之后,catch可能确定该异常必须由函数调用链中更上层的函数来处理,catch能 ...
- 【Intel AF 2.1 学习笔记一】AF程序结构
Intel App Framework(原jqMobi)是用来开发hybrid app的开源免费框架,被intel收编之后发布了最新的2.1版本,最近正在学习.af的所谓程序结构,就是AF网页的架构, ...
- 毕业设计预习:VHDL入门知识学习(一) VHDL程序基本结构
VHDL入门知识学习(一) VHDL程序基本结构 简介 VHDL程序基本结构 简介 概念: HDL-Hardware Description Language-硬件描述语言-描述硬件电路的功能.信号连 ...
随机推荐
- 移动端的silder,未封装,基于zepto的touch模块,有参照修改过touch的bug
<!--html模块--> <header class="appoin-head"> <ul> <li class="aa&qu ...
- 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)
洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...
- PHP 接口 返回构造函数
我们写接口的时候,需要返回json数据,并且里面有错误码,错误信息 还有要返回的数据,这里我构造了一个函数 这里是针对TP5来写的,自己可以根据自己的框架来修改 这样就可以在返回的时候直接用info函 ...
- Linux环境下安装weblogic10.3.2
附件:weblogic10.3.2版本zip包和部署war包提取地址: weblogic.zip:https://pan.baidu.com/s/1Y1tmAhlXsO5Q4zPvOKGG5g 提取 ...
- 第二周Python讲课内容--日记
1.初识模块:sys.os 标准模块库存放在lib文件夹里 三方库模块一般存放在packages文件夹里 模块调用方法:import sys/os sys模块: sys.path 打印环境变量 sys ...
- java中equals方法和hashcode方法的区别和联系,以及为什么要重写这两个方法,不重写会怎样
一.在Object类中的定义为:public native int hashCode();是一个本地方法,返回的对象的地址值.但是,同样的思路,在String等封装类中对此方法进行了重写.方法调用得到 ...
- 简单的 Promise 实现 一
const Promise = function(fn){ let state = { pending: "pending", fulfilled: "fulfilled ...
- 一场IPFS引领下的共享之风正在走向区块链
中国互联网的高速发展 已经接近10年,小编完整的经历这个过程.这一切我们从一个小网站 饭否 说起... 互联网 2006年3月16:Twitter上线 2007年5月12: 饭否上线 饭否是中国第一 ...
- Geth 控制台使用及 Web3.js 使用实战
在开发以太坊去中心化应用,免不了和以太坊进行交互,那就离不开Web3.Geth 控制台(REPL)实现了所有的web3 API及Admin API,使用好 Geth 就是必修课.结合Geth命令用法阅 ...
- PHP 简单的加密解密方法
本算法的基础:给定字符A B,A^B=C,C^B=A,即两次异或运算可得到原字符.实现代码如下: /** * @desc加密 * @param string $str 待加密字符串 * @param ...