【简说Python WEB】Flask应用的文件结构
【简说Python WEB】Flask应用的文件结构
目录
【简说Python WEB】Flask应用的文件结构
1.文件结构的目录
2.配置程序--config.py
3.app应用包
4.剥离出来的email.py
5.蓝本(BLueprint)的应用
6.main目录的error.py代码剥离:
- main目录的view.py代码剥离:
8.主脚本
9.需要安装的依赖包
10.应用启动
附录
系统环境:Ubuntu 18.04.1 LTS
Python使用的是虚拟环境:virutalenv
Python的版本:Python 3.6.9
【简说Python WEB】Flask应用的文件结构
之前,我们应用了如下的组件:
flask-wtf
Flask-SQLAlchemy
Flask-Moment
Jinja2模板
Bootstrap
flask-mail
flask_migrate
因为之前调试和应用组件,插件,导致app.py有一定的体量。对于大多数web应用来说,如果把代码都堆在以前,难以维护。而有一个不错的文件目录组织。可以很好的维护整个项目。通过自我学习,提炼出自己一套容易维护的文件结构。把之前的可以剥离出来的公用模块进行一个分离操作。
1.文件结构的目录
Zflask/
├── app
│ ├── email.py
│ ├── __init__.py
│ ├── main
│ │ ├── errors.py
│ │ ├── forms.py
│ │ ├── __init__.py
│ │ └── views.py
│ ├── models.py
│ └── templates
│ ├── 404.html
│ ├── 500.html
│ ├── base.html
│ ├── index.html
│ └── mail
│ ├── new_user.html
│ └── new_user.txt
├── config.py
├── LICENSE
├── README.md
├── requirements.txt
└── zsdblog.py
app/email.py从原来app.py剥离出来的邮件功能
app/models.py把之前的users模型和roles模型,剥离出来.
app/__init__.py 一些初始化的通用脚本放在这里面,工厂函数
config.py配置文件
zsdblog.py主驱动应用,用于驱动整个项目
requirements.txt依赖包
main/errors.py剥离出来的自定义错误处理程序(剥离原来的程序)
main/forms.py表单处理程序(剥离原来的程序)
main/views.py自定义的应用路由程序(剥离原来的程序)
main/__init__.py 蓝本程序
2.配置程序--config.py
import os
class Config:
SQLALCHEMY_TRACK_MODIFICATIONS = False SECRET_KEY = 'wojiubugaosuni' MAIL_SERVER = 'smtp.qq.com' MAIL_PORT = 587 MAIL_USE_TLS = True MAIL_USERNAME = os.environ.get('MAIL_USERNAME') MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD') ZSD_MAIL_SUBJECT_PREFIX = '[ZSD博客]' ZSD_MAIL_SENDER = 'ZSD博客 管理员 <543421410@qq.com>' ZSD_ADMIN = os.environ.get('ZSD_ADMIN') @staticmethod def init_app(app): pass
class DevelopmentConfig(Config):
DEBUG=True HOSTNAME = '172.30.200.252' DATABASE = 'zsd' USERNAME = 'zsd' PASSWORD = 'zsd' DB_URI = 'mysql+pymysql://{}:{}@{}:3306/{}?charset=utf8mb4'.format( USERNAME, PASSWORD, HOSTNAME, DATABASE) SQLALCHEMY_DATABASE_URI = DB_URI
class TestingConfig(Config):
TESTING = True
class ProductionConfig(Config):
PROD = True
config = {
'development': DevelopmentConfig, 'testing': TestingConfig, 'production': ProductionConfig, 'default': DevelopmentConfig
}
把之前的URI驱动,MAIL配置,封装起来。通过不同的应用环境,调用不同的配置。
3.app应用包
数据库模型app/email.py和电子邮件函数程序app/models.py都移动至app包内。
延迟构建应用实例,把创建过程移动到可以显示调用的工厂函数中
app/__init__.py 代码
from flask import Flask
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) from .main import main as main_blueprint app.register_blueprint(main_blueprint) return app
整个代码中,可以看到引入了许多Flask的扩展。因为还没有初始化所需要的应用实例,这些构建类也没有真正的初始化,只是放在了那里。
必须有一个应用,通过调用create_app函数,才算初始化了。
4.剥离出来的email.py
修改的代码如下:
def send_email(to, subject, template, **kwargs):
app = current_app._get_current_object() msg = Message(app.config['ZSD_MAIL_SUBJECT_PREFIX'] + ' ' + subject, sender=app.config['ZSD_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 = current_app._get_current_object()调用的是current_app而不是原来的app
5.蓝本(BLueprint)的应用
蓝本(BLueprint)实现应用的模块化,可以定义路由和错误处理程序,使得应用层次更清晰。
其中,蓝本中定义的路由和错误处理程序是处在sleep状态。只有蓝本注册到应用上面了,它们才成为应用的一部分。这种插槽式的应用构建,非常灵活。
main/__init__.py 创建蓝本
from flask import Blueprint
main = Blueprint('main', __name__)
from . import views, errors
然后在app/init.py程序中,把蓝本在工厂函数create_app()中注册到应用上。
app/__init__.py 蓝本注册
..
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
return app
6.main目录的error.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, 相当于全局的错误处理程序。
- main目录的view.py代码剥离:
- 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) db.session.commit() session['known'] = False if current_app.config['FLASKY_ADMIN']: send_email(current_app.config['FLASKY_ADMIN'], 'New User', 'mail/new_user', user=user) else: 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))
其中current_app 替换了原来的app
if current_app.config['FLASKY_ADMIN']: send_email(current_app.config['FLASKY_ADMIN'], 'New User', 'mail/new_user', user=user)
url_for('index')需要换成url_for('main.index')main代表这个蓝本下的index路由跳转。
路由装饰器由蓝本提供,所以需要改成:@main.route
8.主脚本
zsdblog.py代码如下:
import os
from flask_migrate import Migrate
from app import create_app, db
from app.models import User, Role
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)
上述脚本,创建一个应用实例,环境变量FLASK_CONFIG可以定义,如果不定义。做默认配置。
这次,可以开启DEBUG模式,如下:
设置环境变量:
(zsdpy1) $ export FLASK_APP=zsdblog.py
(zsdpy1) $ export FLASK_DEBUG=1
9.需要安装的依赖包
(zsdpy1) $ pip freeze >>requirements.txt
10.应用启动
(zsdpy1) $ flask run -h '0.0.0.0' -p 9000
当然如果有db模型更新的话,可以使用
flask db upgrade
更新到最新的模型DDL语。
应用效果如下:
附录
执行代码的时候,出现了如下错误 :
werkzeug.routing.BuildError
werkzeug.routing.BuildError: Could not build url for endpoint 'index'. Did you mean 'main.index' instead?
File "/home/zsd/Zflask/app/main/views.py", line 24, in index
return redirect(url_for('index'))
可以看到/home/zsd/Zflask/app/main/views.py24行代码有问题,修改为如下 :
return redirect(url_for('main.index'))
原文地址https://www.cnblogs.com/zhangshengdong/p/12560353.html

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Android GC原理探究(深度好文)
相信大家都遇到过手机图片滑动卡顿问题,由于不断的GC导致的丢帧卡顿的问题让我们想了很多方案去解决,所以就打算详细的看看内存分配和GC的原理,为什么会不断的GC,GC ALLOC和GC COCURRENT有什么区别,能不能想办法扩大堆内存减少GC的频次等等。 1、JVM内存回收机制 1.1 回收算法 标记回收算法(Mark and Sweep GC) 从"GC Roots"集合开始,将内存整个遍历一次,保留所有可以被GC Roots直接或间接引用到的对象,而剩下的对象都当作垃圾对待并回收,这个算法需要中断进程内其它组件的执行并且可能产生内存碎片 复制算法 (Copying) 将现有的内存空间分为两快,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。 标记-压缩算法 (Mark-Compact) 先需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两...
- 下一篇
Java线程池详解及常用方法
Java线程池详解及常用方法前言最近被问到了线程池的相关问题。于是准备开始写一些多线程相关的文章。这篇将介绍一下线程池的基本使用。 ExecutorsExecutors是concurrent包下的一个类,为我们提供了创建线程池的简便方法。Executors可以创建我们常用的四种线程池:(1)newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。不设上限,提交的任务将立即执行。(2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。(3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。(4)newSingleThreadExecutor 创建一个单线程化的线程池执行任务。 Executors的坏处正常来说,我们不应该使用这种方式创建线程池,应该使用ThreadPoolExecutor来创建线程池。Executors创建的线程池也是调用的ThreadPoolExcutor的构造函数。通过原来可以看出。 我们也看到...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Linux系统CentOS6、CentOS7手动修改IP地址
- Red5直播服务器,属于Java语言的直播服务器
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作