码农行者 码农行者
首页
  • Python

    • 语言特性
    • Django相关
    • Tornado
    • Celery
  • Golang

    • golang学习笔记
    • 对比python学习go
    • 模块学习
  • JavaScript

    • Javascript
  • 数据结构预算法笔记
  • ATS
  • Mongodb
  • Git
云原生
运维
垃圾佬的快乐
  • 数据库
  • 机器学习
  • 杂谈
  • 面试
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

DeanWu

软件工程师
首页
  • Python

    • 语言特性
    • Django相关
    • Tornado
    • Celery
  • Golang

    • golang学习笔记
    • 对比python学习go
    • 模块学习
  • JavaScript

    • Javascript
  • 数据结构预算法笔记
  • ATS
  • Mongodb
  • Git
云原生
运维
垃圾佬的快乐
  • 数据库
  • 机器学习
  • 杂谈
  • 面试
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Python

    • 语言特性

    • Django

    • Best.Practices.for.Django

    • Djangorestfulframework

    • Celery

    • Tornado

    • Flask

      • Flask 目录结构分析
      • FastApi

      • virtualenv

    • Golang

    • Javascript

    • 开发语言
    • Python
    • Flask
    DeanWu
    2018-06-04
    目录

    Flask 目录结构分析

    到目前为止,Flask 最新版本为1.0.3,我们来以此版本做分析,以便可以快速回忆各组件关系。

    基本使用,可参阅官方文档 (opens new window),已非常详尽。

    我们知道Flask,是一个微框架,只所以叫微是因为它没有像Django那样把所有的事情都帮你处理了。它只提供给我们web开发很核心的部分,其他的像数据库处理、模板引擎的选择等都交给了外部的插件处理。这也是Flask的一大特点,插件化。我们可以很灵活的组织我们的项目框架。但有选择,就有问题,这是一柄双刃剑。随着Flask插件生态的繁荣,它已经可以满足大多数的项目需求。甚至github的收藏数已超过Django,稳居python web开发框架之首。一切事物都是相对的,框架亦是如此,没有优劣,只有合适与否。

    那么Flask的插件是如何运作的,一个基本的Flask开发框架都需要什么模块呢?让我们带着这些问题,展开今天的分析。

    # 一个最小的Flask应用

    from flask import Flask
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    if __name__ == '__main__':
        app.run()
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    分析:

    • 1、首先初始化了Flask引用的实例app,这个实例可以提供给wsgi协议的web服务器来运行。也可通过如上的run()函数自己运行,不过这个只限开发,性能非常低下。
    • 2、接下来,在这个app上注册了路由,和处理函数。我们大部分的业务逻辑应该在这个处理函数中。
    • 3、最后,直接返回数据,并没有涉及模板和数据库。

    # 完整项目分析

    以 cookiecutter 模板为例:flask_boilerplate (opens new window)

    项目目录结构如下:

    $ tree
    .
    ├── LICENSE
    ├── Procfile  
    ├── README.rst
    ├── assets   # 静态文件,提供给webpack打包使用
    │   ├── css 
    │   │   └── style.css
    │   ├── img
    │   └── js
    │       ├── main.js
    │       ├── plugins.js
    │       └── script.js
    ├── autoapp.py  # flask app 启动入口
    ├── flask_boilerplate  # flask 代码目录 
    │   ├── __init__.py   
    │   ├── app.py   # flask app 创建代码
    │   ├── commands.py   # flask 命令扩展代码
    │   ├── compat.py   # python 2和3 的兼容代码
    │   ├── database.py   # 数据库 model 代码,可根据复杂程度,分拆多个模块文件
    │   ├── extensions.py   # 扩展统一实例化,方便控制前后顺序,防止循环引用
    │   ├── public   # 蓝图
    │   │   ├── __init__.py 
    │   │   ├── forms.py  
    │   │   └── views.py
    │   ├── settings.py   # 项目整体配置
    │   ├── static   # 静态文件,Flask 默认目录
    │   │   └── build
    │   ├── templates   # 模板文件,flask 默认目录
    │   │   ├── 401.html
    │   │   ├── 404.html
    │   │   ├── 500.html
    │   │   ├── footer.html
    │   │   ├── layout.html
    │   │   ├── nav.html
    │   │   ├── public
    │   │   │   ├── about.html
    │   │   │   ├── home.html
    │   │   │   └── register.html
    │   │   └── users
    │   │       └── members.html
    │   ├── user    # 蓝图
    │   │   ├── __init__.py
    │   │   ├── forms.py
    │   │   ├── models.py
    │   │   └── views.py
    │   └── utils.py  工具包
    ├── package.json   # npm 配置文件
    ├── requirements  # python 模块列表
    │   ├── dev.txt
    │   └── prod.txt
    ├── requirements.txt
    ├── setup.cfg
    ├── tests
    └── webpack.config.js  # webpack配置文件
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55

    我们先忽略其他最外层的配置文件,从入口autoapp.py分析 :

    # -*- coding: utf-8 -*-
    """Create an application instance."""
    from flask.helpers import get_debug_flag
    
    from flask_boilerplate.app import create_app
    from flask_boilerplate.settings import DevConfig, ProdConfig
    
    CONFIG = DevConfig if get_debug_flag() else ProdConfig
    
    app = create_app(CONFIG)
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    分析:

    • 1、实例化了Flask 应用,供外部启动使用。
    • 2、使用全局的配置文件CONFIG,并根据是否调式调用不同的配置项。

    我们继续,到app 文件:

    # -*- coding: utf-8 -*-
    """The app module, containing the app factory function."""
    from flask import Flask, render_template
    
    from flask_boilerplate import commands, public, user
    from flask_boilerplate.extensions import bcrypt, cache, csrf_protect, db, \
        debug_toolbar, login_manager, migrate, webpack
    from flask_boilerplate.settings import ProdConfig
    
    
    def create_app(config_object=ProdConfig):
        """An application factory, as explained here: http://flask.pocoo.org/docs/patterns/appfactories/.
    
        :param config_object: The configuration object to use.
        """
        app = Flask(__name__.split('.')[0])
        app.config.from_object(config_object)
        register_extensions(app)
        register_blueprints(app)
        register_errorhandlers(app)
        register_shellcontext(app)
        register_commands(app)
        return app
    
    .....
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    分析:

    • create_app 函数,在实例化app后,往app上注册了一些基本的扩展和蓝图,以及错误处理和命令上下文等。充分体现了插件的思想。

    那么各模块便体现在 register_extensions 这个函数中:

    def register_extensions(app):
        """Register Flask extensions."""
        bcrypt.init_app(app)
        cache.init_app(app)
        db.init_app(app)
        csrf_protect.init_app(app)
        login_manager.init_app(app)
        debug_toolbar.init_app(app)
        migrate.init_app(app, db)
        webpack.init_app(app)
        return None
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    可以根据命名开出,其中许多必备的扩展插件,如数据库插件。

    除了从功能上来进行扩展外,我们的业务逻辑也可通过蓝图实现插件化, 如下:

    def register_blueprints(app):
        """Register Flask blueprints."""
        app.register_blueprint(public.views.blueprint)
        app.register_blueprint(user.views.blueprint)
        return None
    
    1
    2
    3
    4
    5

    我们的业务逻辑便在这些蓝图中实现。这样我们整个Flask框架整个开发架构便清晰了:

    • 通过扩展来扩展框架功能
    • 通过蓝图来模块化我们的业务逻辑
    #Flask#Python
    上次更新: 2023/03/28, 16:27:19
    SQLAlchemy 数据库链接池问题排查记录
    FastApi 简单入门,附生产级脚手架代码

    ← SQLAlchemy 数据库链接池问题排查记录 FastApi 简单入门,附生产级脚手架代码→

    最近更新
    01
    chromebox/chromebook 刷bios步骤
    03-01
    02
    redis 集群介绍
    11-28
    03
    go语法题二
    10-09
    更多文章>
    Theme by Vdoing | Copyright © 2015-2024 DeanWu | 遵循CC 4.0 BY-SA版权协议
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式