用 Flask 来写个轻博客 (18) — 使用工厂模式来生成应用对象

简介: 目录目录前文列表工厂模式使用工厂方法 Factory Method 创建 app 对象前文列表用 Flask 来写个轻博客 (1) — 创建项目 用 Flask 来写个轻博客 (2) — Hello World! 用 Flask 来写个轻博...

目录

前文列表

用 Flask 来写个轻博客 (1) — 创建项目
用 Flask 来写个轻博客 (2) — Hello World!
用 Flask 来写个轻博客 (3) — (M)VC_连接 MySQL 和 SQLAlchemy
用 Flask 来写个轻博客 (4) — (M)VC_创建数据模型和表
用 Flask 来写个轻博客 (5) — (M)VC_SQLAlchemy 的 CRUD 详解
用 Flask 来写个轻博客 (6) — (M)VC_models 的关系(one to many)
用 Flask 来写个轻博客 (7) — (M)VC_models 的关系(many to many)
用 Flask 来写个轻博客 (8) — (M)VC_Alembic 管理数据库结构的升级和降级
用 Flask 来写个轻博客 (9) — M(V)C_Jinja 语法基础快速概览
用 Flask 来写个轻博客 (10) — M(V)C_Jinja 常用过滤器与 Flask 特殊变量及方法
用 Flask 来写个轻博客 (11) — M(V)C_创建视图函数
用 Flask 来写个轻博客 (12) — M(V)C_编写和继承 Jinja 模板
用 Flask 来写个轻博客 (13) — M(V)C_WTForms 服务端表单检验
用 Flask 来写个轻博客 (14) — M(V)C_实现项目首页的模板
用 Flask 来写个轻博客 (15) — M(V)C_实现博文页面评论表单
用 Flask 来写个轻博客 (16) — MV(C)_Flask Blueprint 蓝图
用 Flask 来写个轻博客 (17) — MV(C)_应用蓝图来重构项目

工厂模式

工厂模式:就是通过某一个接口函数或对象来创建另一个对象,而这个接口函数也称之为工厂函数。 工厂模式使一个类的实例化延迟到其子类。也就是说工厂模式可以推迟到在程序运行的时候才动态决定要创建哪个类的实例,而不是在编译时就必须知道要实例化哪个类

工厂函数:一个用于创建对象的接口(create_object_interface(variables)),让子类来决定(根据不同 variables 作为条件来判断)实例化那一个类的对象。

EXAMPLE:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Circle(object):
    def draw(self):
        print 'draw circle'

class Rectangle(object):
    def draw(self):
        print 'draw Rectangle'

class ShapeFactory(object):
    def create(self, shape):
        if shape == 'Circle':
            return Circle()
        elif shape == 'Rectangle':
            return Rectangle()
        else:
            return None

fac = ShapeFactory()
obj = fac.create('Circle')
obj.draw()

使用工厂方法 Factory Method 创建 app 对象

这样做的好处

  • 可以利用 shell 环境(env)的上下文来动态的改变 app 的初始配置 config,达到了服务器会根据不同的 env 来得到正确 app config 的效果。
  • 这样会让测试变得简单,因为我们随时可以快速的转换 app config 并开展测试。
  • 反之,也能够使用相同的 config 来生成多个相同的 app object,这对在跨多个服务器进行流量负载均衡的时候是很有用的。

  • jmilkfansblog/__init__.py

from flask import Flask, redirect, url_for

from models import db
from controllers import blog

def create_app(object_name):
    """Create the app instance via `Factory Method`"""

    app = Flask(__name__)
    # Set the app config 
    app.config.from_object(object_name)

    # Will be load the SQLALCHEMY_DATABASE_URL from config.py to db object
    db.init_app(app)

    @app.route('/')
    def index():
        # Redirect the Request_url '/' to '/blog/'
        return redirect(url_for('blog.home'))

    # Register the Blueprint into app object
    app.register_blueprint(blog.blog_blueprint)

    return app
  • NOTE 1:将 app.config.from_object(object_name) 接收的参数定义成一个变量,这样就可以通过接收不同类型的实参来生成不同的 app 对象。
  • NOTE 2:在 create_app() 这个函数中,完成了 db/config/route/blueprint 的初始化工作之后,再返回这个 app 对象。

  • manage.py

import os

from flask.ext.script import Manager, Server
from flask.ext.migrate import Migrate, MigrateCommand

from jmilkfansblog import create_app
from jmilkfansblog import models


# Get the ENV from os_environ
env = os.environ.get('BLOG_ENV', 'dev')
# Create thr app instance via Factory Method
app = create_app('jmilkfansblog.config.%sConfig' % env.capitalize())
# Init manager object via app object
manager = Manager(app)

# Init migrate object via app and db object
migrate = Migrate(app, models.db)

# Create some new commands
manager.add_command("server", Server(host='192.168.1.222', port=8089))
manager.add_command("db", MigrateCommand)


@manager.shell
def make_shell_context():
    """Create a python CLI.

    return: Default import object
    type: `Dict`
    """
    return dict(app=app,
                db=models.db,
                User=models.User,
                Post=models.Post,
                Comment=models.Comment,
                Tag=models.Tag,
                Server=Server)

if __name__ == '__main__':
    manager.run()
  • NOTE 1:现在的 manager shell 在每次启动的时候,都会获取一次 OS 的环境变量,并以此来创建 app 对象。
  • NOTE 2:默认使用 DevConfig 配置
  • NOTE 3:这样我们就可以根据手动设置的环境变量来达到生成相应的环境变量的效果,而不需要修改任何源码。

EXAMPLE 1:使用默认配置

(env) [root@flask-dev JmilkFan-s-Blog]# python manage.py shell

>>> app
<Flask 'jmilkfansblog'>
>>> app.config
<Config {'JSON_AS_ASCII': True, 'USE_X_SENDFILE': False, 'SQLALCHEMY_DATABASE_URI': 'mysql+pymysql://root:fanguiju@127.0.0.1:3306/myblog?charset=utf8', 'SQLALCHEMY_TRACK_MODIFICATIONS': None, 'SQLALCHEMY_POOL_SIZE': None, 'SQLALCHEMY_POOL_TIMEOUT': None, 'SESSION_COOKIE_PATH': None, 'SQLALCHEMY_RECORD_QUERIES': None, 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_NAME': 'session', 'SQLALCHEMY_BINDS': None, 'SQLALCHEMY_POOL_RECYCLE': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'LOGGER_HANDLER_POLICY': 'always', 'LOGGER_NAME': 'jmilkfansblog', 'DEBUG': True, 'SQLALCHEMY_COMMIT_ON_TEARDOWN': False, 'SECRET_KEY': 'c8e6ff3e4687709ca10a1138a17cd397', 'EXPLAIN_TEMPLATE_LOADING': False, 'SQLALCHEMY_NATIVE_UNICODE': None, 'MAX_CONTENT_LENGTH': None, 'SQLALCHEMY_ECHO': False, 'APPLICATION_ROOT': None, 'SERVER_NAME': None, 'PREFERRED_URL_SCHEME': 'http', 'JSONIFY_PRETTYPRINT_REGULAR': True, 'TESTING': False, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'PROPAGATE_EXCEPTIONS': None, 'TEMPLATES_AUTO_RELOAD': None, 'TRAP_BAD_REQUEST_ERRORS': False, 'JSON_SORT_KEYS': True, 'JSONIFY_MIMETYPE': 'application/json', 'SQLALCHEMY_MAX_OVERFLOW': None, 'SESSION_COOKIE_HTTPONLY': True, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SESSION_COOKIE_SECURE': False, 'TRAP_HTTP_EXCEPTIONS': False}>

EXAMPLE 2:手动设置使用 Config 配置

(env) [root@flask-dev JmilkFan-s-Blog]# export BLOG_ENV=""
(env) [root@flask-dev JmilkFan-s-Blog]# echo $BLOG_ENV

(env) [root@flask-dev JmilkFan-s-Blog]# python manage.py shell
>>> app.config
<Config {'JSON_AS_ASCII': True, 'USE_X_SENDFILE': False, 'SQLALCHEMY_DATABASE_URI': 'sqlite://', 'SQLALCHEMY_TRACK_MODIFICATIONS': None, 'SQLALCHEMY_POOL_SIZE': None, 'SQLALCHEMY_POOL_TIMEOUT': None, 'SESSION_COOKIE_PATH': None, 'SQLALCHEMY_RECORD_QUERIES': None, 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_NAME': 'session', 'SQLALCHEMY_BINDS': None, 'SQLALCHEMY_POOL_RECYCLE': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'LOGGER_HANDLER_POLICY': 'always', 'LOGGER_NAME': 'jmilkfansblog', 'DEBUG': False, 'SQLALCHEMY_COMMIT_ON_TEARDOWN': False, 'SECRET_KEY': 'c8e6ff3e4687709ca10a1138a17cd397', 'EXPLAIN_TEMPLATE_LOADING': False, 'SQLALCHEMY_NATIVE_UNICODE': None, 'MAX_CONTENT_LENGTH': None, 'SQLALCHEMY_ECHO': False, 'APPLICATION_ROOT': None, 'SERVER_NAME': None, 'PREFERRED_URL_SCHEME': 'http', 'JSONIFY_PRETTYPRINT_REGULAR': True, 'TESTING': False, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'PROPAGATE_EXCEPTIONS': None, 'TEMPLATES_AUTO_RELOAD': None, 'TRAP_BAD_REQUEST_ERRORS': False, 'JSON_SORT_KEYS': True, 'JSONIFY_MIMETYPE': 'application/json', 'SQLALCHEMY_MAX_OVERFLOW': None, 'SESSION_COOKIE_HTTPONLY': True, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SESSION_COOKIE_SECURE': False, 'TRAP_HTTP_EXCEPTIONS': False}>

使用工厂函数生成的 app 对象,能够在程序运行的时候才被决定,这种自动适应不同运行环境的能力,使得程序更加灵活、健壮。

相关文章
|
4月前
|
关系型数据库 数据库连接 数据库
Flask应用基础入门总结
Flask应用基础入门总结
42 0
|
3天前
|
缓存 监控 数据库
Flask性能优化:打造高性能Web应用
【4月更文挑战第16天】本文介绍了提升Flask应用性能的七大策略:优化代码逻辑,减少数据库查询,使用WSGI服务器(如Gunicorn、uWSGI),启用缓存(如Flask-Caching),优化数据库操作,采用异步处理与并发(如Celery、Sanic),以及持续监控与调优。通过这些手段,开发者能有效优化Flask应用,适应大型或高并发场景,打造高性能的Web服务。
|
3天前
|
监控 安全 数据库
Flask应用部署指南:从开发到生产环境
【4月更文挑战第16天】本文是Flask应用从开发到生产的部署指南,涵盖开发环境准备、应用开发、部署方案选择、生产环境配置、应用部署、监控与维护。确保安装Python、Flask及依赖库,使用文本编辑器或IDE编写代码,关注应用安全与性能。选择WSGI服务器、Docker或云服务平台部署,配置生产环境,确保安全性,然后部署应用并进行监控维护,定期更新修复问题,保证应用稳定运行。
|
3天前
|
JSON 安全 API
Flask-Login与Flask-RESTful:扩展你的应用功能
【4月更文挑战第16天】本文介绍了两个实用的Flask扩展——Flask-Login和Flask-RESTful。Flask-Login提供用户认证和会话管理,简化了登录、注销和保护路由的逻辑。而Flask-RESTful则助力构建RESTful API,支持多种HTTP方法和请求解析。通过这两个扩展,开发者能轻松增强Flask应用的功能性,实现安全的用户认证和高效的API交互。
|
4天前
|
数据库 开发者 Python
Python中使用Flask构建简单Web应用的例子
【4月更文挑战第15天】Flask是一个轻量级的Python Web框架,它允许开发者快速搭建Web应用,同时保持代码的简洁和清晰。下面,我们将通过一个简单的例子来展示如何在Python中使用Flask创建一个基本的Web应用。
|
1月前
|
存储 Java UED
如何在Flask应用中实现异步编程?
【2月更文挑战第27天】【2月更文挑战第96篇】如何在Flask应用中实现异步编程?
|
1月前
|
JSON API 数据格式
构建高效Python Web应用:Flask框架与RESTful API设计实践
【2月更文挑战第17天】在现代Web开发中,轻量级框架与RESTful API设计成为了提升应用性能和可维护性的关键。本文将深入探讨如何使用Python的Flask框架来构建高效的Web服务,并通过具体实例分析RESTful API的设计原则及其实现过程。我们将从基本的应用架构出发,逐步介绍如何利用Flask的灵活性进行模块化开发,并结合请求处理、数据验证以及安全性考虑,打造出一个既符合标准又易于扩展的Web应用。
628 4
|
2月前
|
数据库 开发者 Python
Python在Web开发中的应用:Flask与Django框架介绍与实践
Python在Web开发中的应用:Flask与Django框架介绍与实践
|
3月前
|
测试技术 Apache 项目管理
软件测试|探索Flask接口路由技术:构建灵活可拓展的Python应用
软件测试|探索Flask接口路由技术:构建灵活可拓展的Python应用
28 1
|
3月前
|
Ubuntu Docker Python
部署你的flask应用到docker
部署你的flask应用到docker