我们用pycharm去新建Flask项目的时候,会默认生成开发文件.如下,其中包括static,templates,flask1_prj.py文件

在最初开始的时候,我们的app等声明都是在flask1_prj.py中进行的,然后程序实例的运行也是在一起的.就像下面的这样

app = Flask(__name__)

bootstrap=Bootstrap(app)

app.config['SECRET_KEY']=os.urandom(20)

@app.route('/',methods=['GET','POST'])

def hello_world():

form=NameForm()

if form.validate_on_submit():

session['name']=form.name.data

return redirect(url_for('hello_world'))

print session.get('name')

return render_template('index1.html',form=form,name=session.get('name'))

if __name__ == '__main__':

app.run(host='192.168.0.12',port=8000)

这种组织形式在单个文件中开发程序很放方便.但是有个问题是app是在全局作用域中创建.无法动态修改配置.或者我们想建立多个实例的时候,需要为每个实例配置进行不同的配置.在django中我们每创建一个应用实例的时候,相应的文件结构就已经生成好了,不需要我们做另外的配置,但是在Flask中,这些事情需要我们自己来完成.这就需要用到工厂函数了

前面介绍创建不同配置类的时候,我们就新建了一个config.py文件.然后通过配置选项做不同的配置.那么既然我们要建不同的实例,那么就采用调用一个create_app的函数来生成各个不同的实例,在各自生成的实例中再调用不同的配置.这样的结构我们就成为工厂函数,来看具体的代码实现

首先创建工程结构如下.建立一个app的程序包.里面包含__init__.py,config.py,run.py,model_sqlite.py,manger.py

三个文件的作用分别如下,

__init__.py其中就包含工厂函数,是定义工厂函数的地方

config.py 和之前的配置选项一样,定义各种的配置选项

run.py:主程序.

model_sqlite.py是定义数据模型的地方

manger.py 是配置数据迁移的文件

其中还包含main package. main package包含__init__.py和views.py文件

__init__.py是蓝本的定义文件

views.py是定义视图和路由的地方.

接下来看具体的代码实现:

app package:__init__.py

from flask import Flask,render_template

from flask_bootstrap import Bootstrap

from flask_sqlalchemy import SQLAlchemy

import config

from config import DevelopmentConfig

from .main import main as main_blueprint

bootstrap=Bootstrap()

db=SQLAlchemy()

def create_app(config_name):

app=Flask(__name__)

app.config.from_object(DevelopmentConfig)

config.config[config_name].init_app(app)

bootstrap.init_app(app)

db.init_app(app)

app.register_blueprint(main_blueprint)

return app

create_app函数接收config_name参数,然后在其中进行app的生成.生成后进行各种app的绑定.在这里绑定了bootstrap和db.最终返回app实例

app package:config.py 内容和之前一样,没有区别

import os

basedir=os.path.abspath(os.path.dirname(__file__))

class Config:

SECRET_KEY='hello world'

SQLALCHEMY_COMMIT_ON_TEARDOWN=True

ITEMS_PER_PAGE=10

@staticmethod

def init_app(app):

pass

class DevelopmentConfig(Config):

DEBUG=True

SQLALCHEMY_DATABASE_URI='sqlite:///'+os.path.join(basedir,'data.sqlite')

class TestConfig(Config):

TESTING=True

SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'test.sqlite')

WTF_CSRF_ENABLED = False

config={

'development':DevelopmentConfig,

'testing':TestConfig,

'default':DevelopmentConfig

}

app package:model_sqlite.py 内容也和之前一样

from app import db

class User(db.Model):

__tablename__='Users'

id=db.Column(db.Integer,primary_key=True)

name=db.Column(db.String(64),unique=True,index=True)

age=db.Column(db.Integer)

address=db.Column(db.String(100))

role_id=db.Column(db.Integer,db.ForeignKey("Role.id"))

def __repr__(self):

return '<User %r>' % self.name

class Role(db.Model):

__tablename__='Role'

users=db.relationship('User',backref='Role')

id = db.Column(db.Integer, primary_key=True)

name = db.Column(db.String(64), unique=True)

address = db.Column(db.String(100))

def __repr__(self):

return '<User %r>' % self.name

app package:manger.py

from app import create_app

from flask_migrate import Migrate,MigrateCommand

from flask_script import Manager

from app import db

from app.model_sqlite import User,Role

app=create_app('development')

manager=Manager(app)

migrate=Migrate(app,db)

manager.add_command('db',MigrateCommand)

if __name__=="__main__":

manager.run()

不知道大家发现一个问题,在之前单文件配置的时候.程序实例存在与全局作用域中,路由可以直接使用app.route装饰器来定义.但现在程序在运行时创建.只有调用create_app()之后才能使用app.route装饰器.这个时候定义路由就比较晚了.

Flask采用蓝本来解决这个问题,蓝本定义的路由处于休眠状态,直到蓝本注册到程序上时,路由才真正成为程序的一部分

有关于蓝本的具体介绍可以参考下面的2个帖子:

https://www.zhihu.com/question/31748237/answer/55313054

http://dormousehole.readthedocs.io/en/latest/blueprints.html

在main package中就是定义蓝本的地方.

__init__.py

from flask import Blueprint

main=Blueprint('main',__name__,template_folder='../template',static_folder='../static') #template_folder和static_folder分别指示模板文件和静态文件的地址

from . import views

views.py:

from app.main import main

@main.route('/')

def index():

return render_template('index.html')

在具体的视图函数中,就采用的是@main.route(‘/’)的方式,而不是@app.route(‘/’)的方式.

当然最后在其中其中 其中在app.__init__.py的create_app需要将蓝本注册到app当中去.app.register_blueprint(main_blueprint).这样路由就和程序实例关联起来了.

最后在run.py中 通过引用create_app的方式就可以运行整个项目了

from app import create_app

app=create_app('development')

if __name__=="__main__":

app.run(host='192.168.0.12', port=8000)

转载于:https://www.cnblogs.com/zhanghongfeng/p/8447589.html

Flask:工厂函数和蓝本相关推荐

  1. python在工厂中的运用_Python常见工厂函数用法示例

    工厂函数:能够产生类实例的内建函数. 工厂函数是指这些内建函数都是类对象, 当调用它们时,实际上是创建了一个类实例. Python中的工厂函数举例如下: 1. int(),long(),float() ...

  2. [译] ES6+ 中的 JavaScript 工厂函数(第八部分)

    本文讲的是[译] ES6+ 中的 JavaScript 工厂函数(第八部分), 原文地址:JavaScript Factory Functions with ES6+ 原文作者:Eric Elliot ...

  3. 【译】JavaScript 工厂函数 vs 构造函数

    译者:前端小智 原文:medium.com/@chamikakas- 当谈到JavaScript语言与其他编程语言相比时,你可能会听到一些令人困惑东西,其中之一是工厂函数和构造函数. 想优质文章请猛戳 ...

  4. JavaScript中的工厂函数vs构造函数vs class

    原文链接:JavaScript Factory Functions vs Constructor Functions vs Classes 作者:Eric Elliott 译者:sunny 转载需提前 ...

  5. 《流畅的python》学习日志----装饰器工厂函数

    使用装饰器工厂函数实现不同的装饰器行为 想要一个装饰器对不同的函数表现出不同的行为,可以使用装饰器工厂函数,例如: def decorate(type):def calc(func):if type ...

  6. python3精要(19)-全局变量global和工厂函数,lambda,变量作用范围,nonlocal

    一.全局变量global语句: 1.全局变量是位于模块文件的内部顶层的变量名 2.全局变量是在函数内被赋值的话,必须通过global声明 3.全局变量名在函数内部不经营声明也可被引用 二.工厂函数 d ...

  7. Vue——props默认值为工厂函数时[工厂函数:undefined]问题解决方案

    问题描述 methods: {sayHi(){alert('hi');} }, props: {keyword: {default: 'a'},say: {type: Function,default ...

  8. 为类定义后构造函数的最小示例,使用 boost::signals2::deconstruct 作为它的工厂函数

    为类定义后构造函数的最小示例,使用 boost::signals2::deconstruct 作为它的工厂函数 实现功能 C++实现代码 实现功能 为类定义后构造函数的最小示例,使用 boost::s ...

  9. boost::signals2::deconstruct 作为构建后的工厂函数的测试程序

    boost::signals2::deconstruct 作为构建后的工厂函数的测试程序 实现功能 C++实现代码 实现功能 boost::signals2::deconstruct 作为构建后的工厂 ...

  10. SAP UI5 数据绑定中的工厂函数

    工厂函数是一种更强大的从模型数据创建控件的方法. 为控件聚合的每个条目调用工厂函数,开发人员可以决定每个条目是否应由具有不同属性的相同控件表示,甚至每个条目由完全不同的控件表示. 工厂函数带有参数sI ...

最新文章

  1. 【c语言】蓝桥杯算法提高 一元一次方程
  2. c#:未将对象引用设置到对象的实例--可能出现的问题总结(转)
  3. Scala in depth 6 Scala的类型系统 上
  4. 2020 有哪些不容错过的前端技术趋势?
  5. (十)webpack 和 babel
  6. CPU主频频率越高,手机运行速度就越快吗?
  7. 网站等保测评针对服务器,互联互通测评知识分享之信息安全建设要点
  8. 基于框架编写驱动代码
  9. Redis学习一Redis的介绍与安装部署
  10. python基础学习-字符串
  11. TreeMap的排序
  12. 这世上最快的捷径就是脚踏实地
  13. Open Inventor Coin3D
  14. APM Agent 之 动态注入 agent
  15. [软件工程] 可行性研究
  16. 5G大规模天线系统架构探讨
  17. 【PC工具】chrome谷歌浏览器最新离线安装版各种版本,最好用的浏览器没有之一...
  18. 黑苹果和笔记本键盘按键的映射及快捷键的设置
  19. java 龙卷风_java8-lamba表达式的使用-遁地龙卷风
  20. 计算机屏幕分辨率在哪看,在哪看显示器刷新率

热门文章

  1. 扫雷游戏(保姆式教程)
  2. JAVA 实现《超级玛丽升级版》游戏
  3. 还记得JavaWeb中的组件Servlet吗?面试会问
  4. python信用卡客户_银行信用卡客户价值分析(Python数据分析)
  5. c++中调用c编写的动态链接库出现undefined reference to `xxx‘的解决方法
  6. 解决create-react-app 集成ts 报error :because it would overwrite input file. TS5055 问题
  7. ​机器如何“猜你喜欢”?深度学习模型在1688的应用实践
  8. ubuntu/deepin安装配置mysql
  9. python编程从入门到实战16章x轴刻度与书不一样,2020-10-05 Python编程从入门到实践 第16章 下载数据 动手试...
  10. 计算机电源可以改装,闲置的台式机电脑电源别扔了,可以拿来改0-30V可调电源...