Flask_Web学习梳理总结(上)
写在开头:
总结部分为《Flask Web开发》的chapter 1到chapter 10的内容,主要为了理清代码框架的内容,具体到一些具体实现细节不会展开讲,可以看书或网上查找相关资料。为了和书上的代码完全一致,示例用的是原作者最初期的代码版本,地址放在下面。
https://github.com/miguelgrin...
先来认识下面一个最简单的FLASK完整程序,命名为hello.py后运行,然后打开地址栏在地址栏输入http://127.0.0.1:5000/即可在网页上看到一个虽小但完整的Flask程序。
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return '<h1>Hello World!</h1>' if __name__ == '__main__': app.run(debug=True)
这个程序主要包括两个必要的部分:程序实例app 和 路由视图函数@app.route。简单的hello.py程序可能只需要这两个部分,但是当开发的项目较大时,就需要加入更多的东西做支撑,例如加入数据库,蓝图,和一些第三方库让我们的开发更容易实现,这时候就需要包装和丰富程序示例app和路由视图函数@app.route这两个元素。
先看check out 10d 分支得到的代码目录
在这份代码目录中,只需要运行manage.py --runserver可以得到chapter 10之前的完整网页内容。从manage.py的代码开始,create_app为工厂函数,这个函数可以灵活的得到不同配置的程序实例app,输入的唯一参数是程序使用的配置名(这里的os.getenv意思是从环境变量中获取),配置名在config.py中用字典的方式储存,create_app(config_name)函数通过config_name来选择采用哪些配置并和和app做连接,并通过.init_app来传入配置参数 ,函数最后返回一个程序示例app。
manager = Manager(app)这里的Manager类是由Flask-Scripts扩展输出的,Flask-Scripts是为Flask程序添加了命令行解析器的扩展,通过这个扩展,服务器由 manager.run() 启动后就能解析命令行了。
migrate = Migrate(app, db)这里使用Flask-Migrate实现数据库迁移,如果不进行数据库迁移,那么更新数据库就需要每次先删除旧表,再创建一个新表。而数据库迁移技术能增量式地把变化应用到数据库中。这句代码意思注册migrate到实例app上,得到的迁移脚本都会放在migration文件夹里。
make_shell_context() 函数注册了程序、数据库实例以及模型,因此这些对象能直接导入shell.
manager.add_command() 函数在终端环境下添加一个shell命令和db命令.
def test():自定义一个启动单元测试的命令
Manage.py ... app = create_app(os.getenv('FLASK_CONFIG') or 'default') manager = Manager(app) migrate = Migrate(app, db) def make_shell_context(): ... manager.add_command("shell", Shell(make_context=make_shell_context)) manager.add_command('db', MigrateCommand) @manager.command def test(): ...
这里大致就完成了创建程序实例app的部分
下面要完成各个部分网页的路由视图部分,这是程序项目的主要部分,工程文件放在app文件夹内。此文件夹包含四个子文件夹和init.py、decorators.py、email.py、model.py四个独立python文件。auth和main文件夹是区分功能的两个蓝本内容,static是一些静态文件,templates是网页模板。
从app/init.py代码段开始,定义了一个工厂函数created_app(),并将蓝本main和蓝本auth在工厂函数 create_app() 中注册到程序上,最后返回程序实例。
def create_app() ... from .main import main as main_blueprint app.register_blueprint(main_blueprint) from .auth import auth as auth_blueprint app.register_blueprint(auth_blueprint, url_prefix='/auth') return app
这是由于原始的app.route 修饰器只能在调用 create_app() 之后才能使用,这时候这时定义路由就太晚了。同样,自定义的错误页面处理程序也面临相同的困难,因为错误页面处理程序使用 app.errorhandler 修饰器定义。为了解决这个问题,就采用了蓝本的方式。蓝本中定义的路由处于休眠状态,直到蓝本注册到程序上后,路由才真正成为程序的一部分。
对于不同的程序功能,我们要使用不同的蓝本,这是保持代码整齐有序的好方法。这里的代码目录有两个主要蓝本:一般的路由在main蓝本中定义,与用户认证系统相关的路由可在 auth 蓝本中定义。
email.py 通过异步发送电子邮件
decorators.py是为了让视图函数只对具有特定权限的用户开放,而使用的检查用户权限的自定义修饰器。代码里两个修饰器,一个@permission_required用来检查常规权限,一个@admin_required专门用来检查管理员权限。这些自定义的修饰器会在路由视图函数中被使用
例如:
@main.route('/admin') @login_required @admin_required def for_admins_only(): return "For administrators!"
model.py为数据库模型的代码部分,UserMixi是用于认证的Flask-Login扩展提供的一个类,能实现大多数认证的方法。最后,Flask-Login要求程序实现一个回调函数load_user,使用指定的标识符加载用户.加载用户的回调函数接收以Unicode字符串形式表示的用户标识符。如果能找到用户,这个函数必须返回用户对象;否则应该返回 None。
... class Permission '''定义权限常量''' class Role(db.Model) '''定义角色模型''' class User(UserMixin, db.Model): '''定义用户模型''' class AnonymousUser(AnonymousUserMixin): '''定义匿名用户''' ... @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id))
剩下最主要的两个蓝本处理程序,main蓝本和auth蓝本。蓝本下面包括了创建蓝本对象init.py,表单forms.py,视图函数view.py和错误处理error.py几个子PY文件。这两个蓝本文件夹其实为主要工程实现代码文件(通过蓝本处理),里面的init.py负责创建蓝本对象 ,并关联此文件夹下的 view.py(路由处理)和error.py(错误程序)处理。在error.py和view.py的代码下通过已创建的蓝本对象来进行处理相关程序。其中view.py代码会调用文件夹中的form表单。
在app/main/__init__.py实现创建main蓝本,from . import views, errors能把main文件夹下的路由模版和错误处理程序模版与蓝本关联起来。注意,这些模块在app/main/__init__.py脚本的末尾导入,这是为了避免循环导入依赖,因为在views.py和errors.py中还要导入蓝本 main。def inject_permissions()函数为了避免每次调用 render_template() 时都多添加一个模板参数,把Permission类加入模板上下文,使其全局可访问。
from flask import Blueprint main = Blueprint('main', __name__) from . import views, errors from ..models import Permission @main.app_context_processor def inject_permissions(): return dict(Permission=Permission)
框架内容大致就是这样,也在起步学Flask_web,很多地方可能写的不对,欢迎大家交流指出。
转载请署名
最后还有一些学习过程中查阅的技能流相关资料
-------------------------------------------不羁的分割线----------------------------------------------
快速入门Flask: http://docs.jinkan.org/docs/f...
安装和使用SourceTree的Git客户端:http://www.jianshu.com/p/6d27...
⭐GUI for git|SourceTree|入门基础 : http://www.jianshu.com/p/be9f...
理解git的分支Branch :http://blog.csdn.net/lixiaoka...
⭐git分支详解:http://blog.csdn.net/selagine...
使用VirtualEnv虚拟环境(Pycharm) http://blog.csdn.net/langkew/... (选择Epython3.6.3Scriptsenvnscriptsptrhon.exe)
进入源代码目录下,执行virtualenv venv命令即可创建一个名为venv的子文件夹,用来保存一个全新的虚拟环境,但使用之前
需要激活,window下激活命令为venvScriptsactivate,为了提醒你已经激活了虚拟环境,激活虚拟环境的命令提示符会变为(venv) 当虚拟环境的工作完成后,如果你想回到全局的python解释器中,可以在命令行提示符下输入deactivate
Flask路由系统:http://www.jianshu.com/p/e690...
程序上下文和请求上下文的区别(需要激活):https://segmentfault.com/q/10...
https://www.zhihu.com/questio... 不过有一点需要注意的是:在创建“请求上下文”时一定要创建一个“应用上下文”对象。有了“应用上下文”对象,便可以很容易地确定当前处理哪个应用。更像是一个容器,给这个容器注入一些变量,这些变量不仅能在视图方法中用,还能在其他函数中用(尤其是应用上下文,应用在其他地方更为广泛),因为都在这个容器里。“应用上下文”存在的一个主要功能就是确定请求所在的应用。
渲染模板:https://www.liaoxuefeng.com/w...
什么是web表单:http://www.lmlblog.com/2223.html
Flask表单:表单的创建与渲染:https://zhuanlan.zhihu.com/p/...
flask-SQLAlchemy的初级使用教程:https://www.cnblogs.com/alima...
数据库主键和外键:https://www.cnblogs.com/feng9...
使用格式工厂函数:http://blog.csdn.net/hyman_c/...
:http://blog.csdn.net/rubik_wo...
发现register_blueprint()函数的作用就是把蓝本对象main注册到了其一个list中blueprints,我们可以做这样的猜想,当用户在输入URL中,程序内部会从app类中的蓝本list中找到这个蓝本对象main,然后再从main中找到对应的templates或者static资源路径
这里flask web 开发那本书没有说到的一点就是,flask的所有扩展都被设计成了可以先创建应用程序,然后再导入app 应用变量,因为如上面的 db=sqlalchemy() 都是全局的,而app 则可以有不止一个,所以设计成了先创建应用程序扩展,再绑定app,再通过form_object导入 实现好的config 配置 其中的一些配置在通过init_app传入相应程序中,最后通过 crate_app()来进行调用, os.getenv()来获取环境变量中的flask_config.然后执行。
如何理解flask中的蓝本:https://www.zhihu.com/questio...
Python 的@用法:http://blog.csdn.net/Sean_ran...
@property:https://www.liaoxuefeng.com/w...