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 分支得到的代码目录
Flask_Web学习梳理总结(上)

在这份代码目录中,只需要运行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是网页模板。

Flask_Web学习梳理总结(上)

从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表单。

Flask_Web学习梳理总结(上)

在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...

相关推荐