《Flask Web开发:基于Python的Web应用开发实战》笔记(原创)
内容提要
在学习“狗书”《Flask Web开发:基于Python的Web应用开发实战》的过程中,一直遇到各种各样的坑。该书的第一部分是“Flask简介”,主要介绍的一些基础知识。第二部分是“实例:社交博客程序”,讲的是如何搭建一个社交博客的框架。目前我学到第二部分,回过头来看,觉得按照程序运行的实际逻辑来说明程序的原理,并在这个过程中分析遇到的各种“坑”,也更能让人理解(至少让我自己理解)。
正文
- 程序包结构
flask文件夹结构
其中:
app为程序包,Flask程序保存在这个包中
migrations文件夹包含数据库迁移脚本
tests包保存单元测试
requirements文件夹中记录程序的依赖
config.py是程序的配置文件
manage.py是程序的运行文件,用于启动程序即程序的其他任务
app包结构
其中:
auth为保存专门用于认证的auth蓝本
main为保存main蓝本的包
static文件夹用于保存静态文件,例如HTML代码中引用的图片、 JavaScript 源码文件和 CSS
templates用于保存网页的模板
蓝本文件夹结构(以auth文件夹为例,main蓝本等不再赘述)
蓝本的细节就不在此赘述,在flask框架中用到蓝本,可以对不同的程序功能使用不同的蓝本,这是保证程序整齐有序的办法。(想想把所有功能都写在一起会多么混乱)。这里说明一下到蓝本的程序运行原理:app/auth/views.py 模块引入蓝本,然后使用蓝本的 route 修饰器定义与认证相关的路由,然后再渲染views中设定的网页模板。看起来是不是如果程序能运行到蓝本这一步,我们就可以对网页进行操作了。
2. 运行说明
在运行程序的时候,我们在虚拟环境下,通过如下命令来完成。由此可见,程序的运行是由manage.py来开始的。
(venv) $ python manage.py runserver
那么,我们来看看这个manage.py吧,期待不期待?兴奋不兴奋?
#!/usr/bin/env python
import os
COV = None
if os.environ.get('FLASK_COVERAGE'):import coverageCOV = coverage.coverage(branch=True, include='app/*')COV.start()if os.path.exists('.env'):print('Importing environment from .env...')for line in open('.env'):var = line.strip().split('=')if len(var) == 2:os.environ[var[0]] = var[1]from app import create_app, db
from app.models import User, Follow, Role, Permission, Post, Comment
from flask_script import Manager, Shell
from flask_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, Follow=Follow, Role=Role,Permission=Permission, Post=Post, Comment=Comment)
manager.add_command("shell", Shell(make_context=make_shell_context))
manager.add_command('db', MigrateCommand)@manager.command
def test(coverage=False):"""Run the unit tests."""if coverage and not os.environ.get('FLASK_COVERAGE'):import sysos.environ['FLASK_COVERAGE'] = '1'os.execvp(sys.executable, [sys.executable] + sys.argv)import unittesttests = unittest.TestLoader().discover('tests')unittest.TextTestRunner(verbosity=2).run(tests)if COV:COV.stop()COV.save()print('Coverage Summary:')COV.report()basedir = os.path.abspath(os.path.dirname(__file__))covdir = os.path.join(basedir, 'tmp/coverage')COV.html_report(directory=covdir)print('HTML version: file://%s/index.html' % covdir)COV.erase()@manager.command
def profile(length=25, profile_dir=None):"""Start the application under the code profiler."""from werkzeug.contrib.profiler import ProfilerMiddlewareapp.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[length],profile_dir=profile_dir)app.run()@manager.command
def deploy():"""Run deployment tasks."""from flask_migrate import upgradefrom app.models import Role, User# migrate database to latest revisionupgrade()# create user rolesRole.insert_roles()# create self-follows for all usersUser.add_self_follows()if __name__ == '__main__':manager.run()
下面我们按照顺序去理一下,看看manage.py到底是如何运行的。
import os
COV = None
if os.environ.get('FLASK_COVERAGE'):import coverageCOV = coverage.coverage(branch=True, include='app/*')COV.start()
?这段代码是关于程序测试覆盖度方面的,我们可以先行略去,测试本身并不影响程序的运行。
if os.path.exists('.env'):print('Importing environment from .env...')for line in open('.env'):var = line.strip().split('=')if len(var) == 2:os.environ[var[0]] = var[1]
?这段代码的作用是从.env文件中导入环境变量。具体的大家可以去搜索一下这个文件,在程序配置中,有些信息是在环境变量中设置的。但是此处我们也略过细节。
from app import create_app, db
from app.models import User, Follow, Role, Permission, Post, Comment
from flask_script import Manager, Shell
from flask_migrate import Migrate, MigrateCommand
?各种导入,从app包中导入create_app工厂函数和数据库db。从app.models模块中导入User, Follow, Role, Permission, Post, Comment等类。在flask_script扩展中导入Manager, Shell, 从flask_migrate扩展中导入Migrate, MigrateCommand。什么意思呢?自己去搜索一下。
此处有一个坑:在原文中flask的扩展采用from flask.ext.script import Manager, Shell的导入方式,但是实际用的时候却会报错,从报错的信息中可以知道flask.ext.script已经弃用了,改为flask_script即可。其他的扩展也是一样。
>>> from flask.ext.script import Manager
__main__:1: ExtDeprecationWarning: Importing flask.ext.script is deprecated, use flask_script instead.
让我们继续吧!
app = create_app(os.getenv ('FLASK_CONFIG') or 'default')
这一句是创建工厂函数的实例,create_app是由from app import create_app, db导入的。
这里有一个坑需要注意一下,from app import create_app, db中的app是我们创建的一个包,其放置于顶层文件夹中,其中包括一个__init__.py文件。而语句app = create_app(os.getenv (‘FLASK_CONFIG’) or ‘default’)的app则是给create_app函数创建的实例的一个命名,这两个的含义是不一样的。对于我这种小白,刚刚开始也是迷惑了一阵子。
现在我们来看一下具体实现的方法。
os.getenv(‘FLASK_CONFIG’) or ‘default’),这个’FLASK_CONFIG’我们是我们设置的环境变量,通过os.getenv我们可以获得这个环境参数。因为这是对工厂函数create_app进行实例化,因此我们得到的环境参数就作为create_app的参数,如果没有设置’FLASK_CONFIG’这个环境变量,那么就将’default’这个默认值赋给工厂函数。那么这个设置的’FLASK_CONFIG’环境变量或这个’default’到底是什么呢?这需要到工厂函数中看一下。
既然create_app是从app包中导入的,那么让我们一起来看看这个包里面都有什么吧!打开app下面的__init__.py文件,看到没有create_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 flask_login import LoginManager
from flask_pagedown import PageDown
from config import config
#依旧是各种导入,这里应该不难理解,在工厂函数中导入了flask及其扩展,也通过from config import config导入了程序配置文件config.py中的config属性bootstrap = Bootstrap()
mail = Mail()
moment = Moment()
db = SQLAlchemy()
pagedown = PageDown()login_manager = LoginManager()
login_manager.session_protection = 'strong'
login_manager.login_view = 'auth.login'
#这里是创建导入的Flask扩展的实例。def create_app(config_name): app = Flask(__name__) #创建Flask的实例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)login_manager.init_app(app)pagedown.init_app(app)#创建flask扩展的实例if not app.debug and not app.testing and not app.config['SSL_DISABLE']:from flask_sslify import SSLifysslify = SSLify(app)from .main import main as main_blueprintapp.register_blueprint(main_blueprint)from .auth import auth as auth_blueprintapp.register_blueprint(auth_blueprint, url_prefix='/auth')from .api_1_0 import api as api_1_0_blueprintapp.register_blueprint(api_1_0_blueprint, url_prefix='/api/v1.0')#注册蓝图到工厂函数中return app
广告结束,继续manage.py
app = create_app(os.getenv ('FLASK_CONFIG') or 'default')
def create_app(config_name):app = Flask(__name__)app.config.from_object(config[config_name])
config = {'development': DevelopmentConfig,'testing': TestingConfig,'production': ProductionConfig,'heroku': HerokuConfig,'unix': UnixConfig,'default': DevelopmentConfig
}
class DevelopmentConfig(Config):DEBUG = TrueSQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')
config[config_name].init_app(app)
@staticmethoddef init_app(app):pass
bootstrap.init_app(app)mail.init_app(app)moment.init_app(app)db.init_app(app)login_manager.init_app(app)pagedown.init_app(app)
if not app.debug and not app.testing and not app.config['SSL_DISABLE']:from flask_sslify import SSLifysslify = SSLify(app)
?这里是启用安全HTTP的flask扩展flask_sslify,先略去。
from .main import main as main_blueprintapp.register_blueprint(main_blueprint)from .auth import auth as auth_blueprintapp.register_blueprint(auth_blueprint, url_prefix='/auth')from .api_1_0 import api as api_1_0_blueprintapp.register_blueprint(api_1_0_blueprint, url_prefix='/api/v1.0')
manager = Manager(app)
migrate = Migrate(app, db)
总结
通过运行manage.py的过程分析,发现总体框架特点如下:
manage.py——公司的总经理
工厂函数——项目经理
config.py——公司财务总监
蓝本——各技术部门经理
视图文件——广大苦逼工程师
template/form——生产工具(枪/炮)
总经理:干
项目经理:好, 财务总监,这粮和钱…, 部门经理们,我给你们说个事呗
财务总监:有的,你有我有全都有。都在这里,别客气
技术部门经理:好的。那啥,小明,小红,抄家伙
工程师:…(端着枪扛着炮就冲出去了)
《Flask Web开发:基于Python的Web应用开发实战》笔记(原创)相关推荐
- 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)
目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构 前言 学习Python也有一个半月时间了,学到现在感觉还是 ...
- 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(下)
目录 前言 第8章 用户认证 第9章 用户角色 第10章 用户资料 第11章 博客文章 第12章 关注者 第13章 用户评论 第14章 应用编程接口 前言 第1章-第7章学习实践记录请参见:< ...
- flask web开发:基于python的web应用开发实战_在知乎上学 Python Web 开发篇
通知: 1. 最近我们将进行2期学习小组,面向完全零基础的Python入门学习小组已经开始,第一次任务的讨论将于明晚(15号)进行,现在上车还来得及 2. 另有一期数据可视化小组将于年前启动,第一次讨 ...
- 《Flask Web开发——基于Python的Web应用开发实践》代码使用方法
git clone https://github.com/miguelgrinberg/flasky.git 然后书上遍地的git checkout 1a这样的命令,怎么回事呢? 先把上面的命令在一个 ...
- CANanlystII 基于python的二次开发实践
前期,我已经编写过一篇<CANanlystII 基于linux的二次开发实践>这篇博客承接上一篇博客,所以背景知识和测试场景,就不再赘述. 背景知识和测试场景,可以查阅如下: CANanl ...
- 学习《Flask Web开发:基于Python的Web应用开发实战》分享
学习<Flask Web开发:基于Python的Web应用开发实战>分享一直在说学习Python,对同事,对朋友,都说我正在学习Python,这无形给自己一定的压力,促使自己要去学习,进步 ...
- Flask Web开发:基于Python的Web应用开发实战
<Flask Web开发:基于Python的Web应用开发实战> 虽然简单的网站(Flask+Python+SAE)已经上线,但只是入门.开发大型网站,系统地学习一遍还是有必要的. 201 ...
- 《FlaskWeb开发:基于Python的Web应用开发实战》笔记
开源库的cdn加速 可以在这里直接搜索复制script链接 https://www.bootcdn.cn/ requirements.txt文件的生成与使用 生成requirements文件:$ pi ...
- w3af 基于Python的Web应用扫描器
全称"Web Application Attack and Audit Framework"--Web应用程序攻击审计框架.W3af是一个基于Python的Web应用扫描器.W3a ...
最新文章
- 机器学习中算法的性能评估
- go kegg_零基础 GO 与 KEGG 分析,手把手教你用多种途径实现!
- ssh报错 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
- 怎样在IDEA上将WebService接口打包部署到服务器
- HttpClient常用的一些常识
- 4.线性和卷积——不同种类的噪声、中值滤波器揭破和实战_5
- python 标签字体大小_这文档动画,怎么用 Python 实现的?
- JAVE amr转换mp3
- 爬虫抓包,模拟提交、Fiddler和Postman结合Chrome的使用
- word公式编辑器软件
- python打开pcap文件_python 抓包保存为pcap文件并解析的实例
- java连连看代码_Java版连连看
- 【2022省选模拟】叮叮车——卡特兰数、数位DP
- Android自定义IM聊天界面
- storyboard 苹果启动图_iOS 13使用LaunchScreen.storyboard适配各尺寸启动图
- Linux的目录挂载详解
- 2019杭电多校 第七场 Kejin Player 6656(求期望值)
- 2.1安装前的准备工作---安装Red Hat Linux
- 蚂蚁森林师生执念种上万棵树
- IE和Firefox兼容性