系统环境: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, 相当于全局的错误处理程序。

7. main目录的view.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)
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'))

【简说Python WEB】Flask应用的文件结构的更多相关文章

  1. 【简说Python WEB】数据库

    目录 [简说Python WEB]数据库 数据库表 docker安装MySQL Flask-SQLAlchemy操纵MySQL数据库 初始化 定义模型 定义关系 数据库的CRUD操作 创建表 inse ...

  2. 【简说Python WEB】Flask-Moment

    目录 [简说Python WEB]Flask-Moment 系统环境:Ubuntu 18.04.1 LTS Python使用的是虚拟环境:virutalenv Python的版本:Python 3.6 ...

  3. 【简说Python WEB】视图函数操作数据库

    目录 [简说Python WEB]视图函数操作数据库 系统环境:Ubuntu 18.04.1 LTS Python使用的是虚拟环境:virutalenv Python的版本:Python 3.6.9 ...

  4. 【简说Python WEB】Web应用部署

    目录 [简说Python WEB]Web应用部署 应用层 缓存层 数据层 Gunicorn 的应用 1.安装Gunicorn 2.Gunicorn的启动 Nginx 的应用 1.docker方式部署安 ...

  5. 【简说Python WEB】pyechart在flask中的应用

    个人笔记总结,可读性不高.只为自己总结用.怕日后忘记. 这里用到了tushare,pandas等python组件. pyechart的案例 c = ( Bar() .add_xaxis([" ...

  6. python web -- flask

    Flask是一个简洁的 Python_web 框架. 零. virtualenv 虚拟环境配置. $ easy_install pip $ pip install virtualenv $ virtu ...

  7. Python Web Flask源码解读(一)——启动流程

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  8. Python Web Flask源码解读(二)——路由原理

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  9. 【简说Python WEB】flask-mail电子邮件

    目录 flask-mail flask shell发送邮件 系统环境:Ubuntu 18.04.1 LTS Python使用的是虚拟环境:virutalenv Python的版本:Python 3.6 ...

随机推荐

  1. 吴裕雄--天生自然 R语言开发学习:重抽样与自助法(续一)

    #-------------------------------------------------------------------------# # R in Action (2nd ed): ...

  2. JVM类文件结构

    作为一名Java后台开发的程序员, 深入理解JVM, 重要性不言而喻, 这篇文章主要是记录JVM类文件结构相关知识. 2. 实例 这部分比较抽象, 所以以实例的形式来学习. 这部分作为资料, 以便后面 ...

  3. CentOS7用yum安装wget命令后仍然提示命令找不到的解决方法

    需求:用的AWS实例自带的CentOS7用yum安装wget命令后扔提示命令找不到,后面用源码安装方式解决,下面先讲解决方法,疑问及知识点扩展最后写出 1.问题(因是mini版本系统,有些基本命令扔需 ...

  4. Proto3:Arena分配指南

    Arena分配是仅C++有的功能,在使用Protocol Buffer时,它可以帮助你优化你的内存使用,提高性能.在.proto文件中启用Arena分配会在生成的C++代码中添加处理Arena分配的额 ...

  5. 网购分期不还 N种恶果等着你

    N种恶果等着你" title="网购分期不还 N种恶果等着你"> 网购市场狂飙突进的发展,让每个人都享受到随时随地购物的乐趣,也在很大程度上推动商品之间的流通.目前 ...

  6. iOS多线程开发之GCD(基础篇)

    总纲: GCD基本概念 GCD如何实现 GCD如何使用 队列和任务组合 一.GCD基本概念 GCD 全称Grand Central Dispatch(大中枢队列调度),是一套低层API,提供了⼀种新的 ...

  7. 启动tomcat报错 Unable to process Jar entry [module-info.class] from Jar...[xxx.xx.jar!\] for annotations

    Java Web 项目tomcat启动报错module-info.class 从git 上面拉下的项目,运行报错. jdk.maven配置正常 tomcat启动遇见的问题: Unable to pro ...

  8. 6487. 【GDOI2020模拟02.29】列强争霸war

    题目描述 区间绝对众数 即出现次数>len/2下取整的数 对于区间[L,R]扫一遍,维护一个数x和出现次数s 当前数=x则s+1,否则s-1,若s已为0则把x设为当前数 若区间内存在绝对众数,那 ...

  9. P1678 烦恼的高考志愿

    P1678题库链接:https://www.luogu.org/problem/P1678 难度:普及- 算法标签:模拟,贪心,排序,二分查找 1.朴素模拟 O(m*n) 得分30 先将m个学校的录取 ...

  10. PHP时区转换(默认中国时区<Asia/Shanghai>转意大利时区<Europe/Rome>)

    <?php function changeTimeZone($date_time, $format = 'Y-m-d H:i:s', $to = 'Europe/Rome', $from = ' ...