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 学习 六 大型程序结构的更多相关文章

  1. Celery 与 Flask 大型程序结构的结合

    :first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; m ...

  2. Python学习笔记(Ⅰ)——Python程序结构与基础语法

    作为微软的粉丝,最后终于向Python低头了,拖了两三个月终于下定决心学习Python了.不过由于之前受到C/C#等语言影响的思维定式,前期有些东西理解起来还是很费了些功夫的. 零.先抄书: 1.Py ...

  3. flask学习(六):URL传参

    1. 参数的作用:可以在相同的URL,但是指定不同的参数,来加载不同的数据 例如:简书上每一篇文章前面的URL相同,只是后面的参数不同 2. 在flask中如何使用参数: 注意: 1) 参数需要放在两 ...

  4. [ Python ] Flask 基于 Web开发 大型程序的结构实例解析

    作为一个编程入门新手,Flask是我接触到的第一个Web框架.想要深入学习,就从<FlaskWeb开发:基于Python的Web应用开发实战>这本书入手,本书由于是翻译过来的中文版,理解起 ...

  5. c# 程序结构

    最近工作中需要用到c#,所以从今天开始博客不定期更新c#学习笔记 c#程序结构大体分为, 命名空间 类 Main 方法   命名空间 相当于一个仓库 通过 using 引入命名空间 比如 using ...

  6. Flask从入门到精通之大型程序的结构一

    尽管在单一脚本中编写小型Web 程序很方便,但这种方法并不能广泛使用.程序变复杂后,使用单个大型源码文件会导致很多问题.不同于大多数其他的Web 框架,Flask 并不强制要求大型项目使用特定的组织方 ...

  7. C++ Primer 学习笔记_88_用于大型程序的工具 --异常处理[续1]

    用于大型程序的工具 --异常处理[续1] 四.又一次抛出 有可能单个catch不能全然处理一个异常.在进行了一些校正行动之后,catch可能确定该异常必须由函数调用链中更上层的函数来处理,catch能 ...

  8. 【Intel AF 2.1 学习笔记一】AF程序结构

    Intel App Framework(原jqMobi)是用来开发hybrid app的开源免费框架,被intel收编之后发布了最新的2.1版本,最近正在学习.af的所谓程序结构,就是AF网页的架构, ...

  9. 毕业设计预习:VHDL入门知识学习(一) VHDL程序基本结构

    VHDL入门知识学习(一) VHDL程序基本结构 简介 VHDL程序基本结构 简介 概念: HDL-Hardware Description Language-硬件描述语言-描述硬件电路的功能.信号连 ...

随机推荐

  1. Weex 初探

    Weex 初探 Weex 介绍 Weex 是阿里于 2016 年开源的一款开发框架,它的介绍是: Weex 是一个使用 Web 开发体验来开发高性能原生应用的框架. 它使用了 Web 技术来开发 An ...

  2. 【BZOJ3223】文艺平衡树(Splay)

    题面 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...

  3. CTSC 选课

    题面(有删减) 题目描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修了这M门 ...

  4. Couldn't save uncommitted changes.

    关于idea切换分支报错的问题. Couldn't save uncommitted changes. Tried to save uncommitted changes in stash befor ...

  5. 应用canvas绘制动态时钟--每秒自动动态更新时间

    使用canvas绘制时钟 下文是部分代码,完整代码参照:https://github.com/lemoncool/canvas-clock,可直接下载. 首先看一下效果图:每隔一秒会动态更新时间 一. ...

  6. Scala编程快速入门系列(二)

    目    录 一.Scala概述 二.Scala数据类型 三.Scala函数 四.Scala集合 五.Scala伴生对象 六.Scala trait 七.Actor 八.隐式转换与隐式参数 九.Sca ...

  7. 【OpenCV-Python:实现人脸、人眼、嘴巴识别】实战(一)

    AI时代的到来,手机上的APP开始应用人脸识别去完成事情,如iphoneX的人脸解锁,百度自动贩卖机的人脸识别系统进行支付,支付宝的人脸识别登录等,提高了使用软件的易用性,但也因为其便利性,在某些市面 ...

  8. Java面试宝典笔记录

    1.一个.java文件中可以有多个类(不是内部类),但是只能有一个public类,且类名和文件同名.(一般不提倡这么写,一类一文件) 2.java保留字:goto, const. 3.访问权限控制 访 ...

  9. Maven-01: Maven入门

    先看看开发环境: 我们在E盘下新建一个文件夹叫helloworld,这个文件夹下建一个src文件夹和一个文件pom.xml. src下的目录结构为: pom.xml文件内容为: <?xml ve ...

  10. Vue之八 HTML5 History模式

    nginx配置 location / { root /webroot/www/ShopMall3; try_files $uri $uri/ /index.html; } /:访问路径: root:服 ...