Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog

目录

前文列表

用 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 对象,能够在程序运行的时候才被决定,这种自动适应不同运行环境的能力,使得程序更加灵活、健壮。

用 Flask 来写个轻博客 (18) — 使用工厂模式来生成应用对象的更多相关文章

  1. 用 Flask 来写个轻博客

    用 Flask 来写个轻博客 用 Flask 来写个轻博客 (1) — 创建项目 用 Flask 来写个轻博客 (2) — Hello World! 用 Flask 来写个轻博客 (3) — (M)V ...

  2. 用 Flask 来写个轻博客 (37) — 在 Github 上为第一阶段的版本打 Tag

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 第一阶段结语 打 Tag 前文列表 用 Flask 来写个轻博客 (1 ...

  3. 用 Flask 来写个轻博客 (36) — 使用 Flask-RESTful 来构建 RESTful API 之五

    目录 目录 前文列表 PUT 请求 DELETE 请求 测试 对一条已经存在的 posts 记录进行 update 操作 删除一条记录 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 ...

  4. 用 Flask 来写个轻博客 (35) — 使用 Flask-RESTful 来构建 RESTful API 之四

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 POST 请求 身份认证 测试 前文列表 用 Flask 来写个轻博客 ...

  5. 用 Flask 来写个轻博客 (34) — 使用 Flask-RESTful 来构建 RESTful API 之三

    目录 目录 前文列表 应用请求中的参数实现 API 分页 测试 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hello World! 用 F ...

  6. 用 Flask 来写个轻博客 (33) — 使用 Flask-RESTful 来构建 RESTful API 之二

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 构建 RESTful Flask API 定义资源路由 格式 ...

  7. 用 Flask 来写个轻博客 (32) — 使用 Flask-RESTful 来构建 RESTful API 之一

    目录 目录 前文列表 扩展阅读 RESTful API REST 原则 无状态原则 面向资源 RESTful API 的优势 REST 约束 前文列表 用 Flask 来写个轻博客 (1) - 创建项 ...

  8. 用 Flask 来写个轻博客 (31) — 使用 Flask-Admin 实现 FileSystem 管理

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 编写 FileSystem Admin 页面 Flask-A ...

  9. 用 Flask 来写个轻博客 (30) — 使用 Flask-Admin 增强文章管理功能

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 实现文章管理功能 实现效果 前文列表 用 Flask 来写个 ...

随机推荐

  1. Vue3.0响应式实现

    基于Proxy // 弱引用映射表 es6 防止对象不能被回收 let toProxy = new WeakMap(); // 原对象: 代理过得对象 let toRaw = new WeakMap( ...

  2. linux配置mysql数据库远程连接失败

    今天配置linux下mysql数据库可以远程访问的问题,百度这方面的资料有很多,但是方法都一样,都试过了却未能解决,记录一下 第一步:在/etc/mysql/my.cnf下找到bind-address ...

  3. TCL自动化之SSH交互式

    目前ssh工具很多,但是能够轻松运用到自动化脚本中,可以轻松适配任何环境,满足ssh交互式登录的tcl工具包很少 下面是个人在tcl自动化过程中比较满意的一款自动化脚本 通过使用管道方式分装plink ...

  4. Python_pickle

    pickle是一个可以将任意一个对象存储在硬盘文件中的工具. 更新:Python3中用法变了:  https://www.cnblogs.com/fmgao-technology/p/9078918. ...

  5. jQuery easyUI 使用 datagrid 表格

    获取后台数据依旧是使用一般处理程序(ashx) ,分页上添加一个函数(pagerFilter(data)) 前端代码: <%@ Page Language="C#" Auto ...

  6. Task总结

    1.Task的优势 ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便.比如: ◆ ThreadPool不支持线程的取消.完成.失败通知等交互性 ...

  7. winform中进行post上传文件

    winform中要上传文件到远程的服务器上面,我在本地用的是post方式传递数据,用的是HTTP协议,具体代码如下: 下面的代码就是一个上传的方法,参数需要路径和文件路径就可以了,我本地winform ...

  8. CSS-06 外部JS,CSS文件的寻址问题

    如果js.css外部文件有使用到相对路径,其相对路径的基准是不一样的 当一个index.html中引入外部的JS和CSS文件时: 在index.css文件中,相对路径的写法是以css文件相对于img图 ...

  9. react native 之 Android studio

    https\://services.gradle.org/distributions/gradle-4.4-all.zip 下载失败 https://blog.csdn.net/u013132758/ ...

  10. CMS(1)

    一周后,终于可以学习到可爱的渗透了哈哈哈.除了大哥给的CMS(其实可以算是只是在文件上传的时候了解一下),但是对于一个CMS完整的渗透思路,我还是不懂.首先感谢章老师给我的CMS源码哈哈哈,在我的日记 ...