我们用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)

Flask:工厂函数和蓝本的更多相关文章

  1. flask实战-个人博客-使用工厂函数创建程序实例 --

    使用工厂函数创建程序实例 使用蓝本还有一个重要的好处,那就是允许使用工厂函数来创建程序实例.在OOP(Object-Oriented Programming,面向对象编程)中,工厂(factory)是 ...

  2. (转)论python工厂函数与内建函数

    所谓工厂函数就是指这些内建函数都是类对象, 当你调用它们时,实际上是创建了一个类实例.   工厂函数: int(),long(),float(),complex(),bool() str(),unic ...

  3. jQuery基础的工厂函数以及定时器的经典案例

    1. jQuery的基本信息:  1.1 定义: jQuery是JavaScript的程序库之一,它是JavaScript对象和实用函数的封装, 1.2 作用: 许多使用JavaScript能实现的交 ...

  4. jQuery基础,定时器,工厂函数

    这个星期刚刚学的JQuery,下面我来说说我学的这几个例子 jQuery是JavaScript的一个程序库. Jquery的工厂函数$(): 在Jquery中 $符号等价于jquery,作用是将DOM ...

  5. jQuery1.11源码分析(4)-----Sizzle工厂函数[原创]

    在用前两篇讲述完正则表达式.初始化.特性检测之后,终于到了我们的正餐——Sizzle工厂函数! Sizzle工厂函数有四个参数, selector:选择符 context:查找上下文 results: ...

  6. python--字符工厂函数dict()

    字符工厂函数str() class str(object): """ str(object='') -> str str(bytes_or_buffer[, enc ...

  7. Python 工厂函数和内建函数

    工厂函数 工厂函数都是类对象, 即当你调用他们时, 创建的其实是一个类实例 例如: str(), list(), tuple()... 内建函数 内建函数通常是python自定义的一些函数, 这些函数 ...

  8. Javascript我学之六对象工厂函数与构造函数

    本文是金旭亮老师网易云课堂的课程笔记,记录下来,以供备忘. 概述 使用对象字面量,或者向空对象中动态地添加新成员,是最简单易用的对象创建方法. 然而,除了这两种常用的对象创建方式,JavaScript ...

  9. python之工厂函数

    python之工厂函数 本人也是小白一个,最近在学习python工厂函数时随便在网上搜了搜,发现许多人对工厂函数的理解存在误区,同时也是为了整理和记录自己的思路,写下本片博文. 工厂函数顾名思义就是一 ...

随机推荐

  1. 一个项目多个App项目搭建

    在testDjango项目中找到testDjango文件夹,打开urls.py路由配置文件并添加以下配置 from django.conf.urls import url,includefrom dj ...

  2. Flutter接入极光推送

    (1)搜索 https://pub.dartlang.org/packages/jpush_flutter ,安装插件,并且按照官方配置 /android/app/build.gradle andro ...

  3. android MPChart图标使用具体解释

    近期项目里有要加入更加复杂的图标了,曾经一些简单的曲线图,饼状图.风险指示图等,都是自己画.随着难度的添加.越来越力不从心.曾经研究过achartenginee图标框架,但发现achartengine ...

  4. Shell脚本值:运算符

    算术运算符 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用. expr 是一款表达式计算工具,使用它能完成表达式的求值操作. 例如:实现两个 ...

  5. 【Excle数据透视表】如何重命名数据透视表

    如下图,是新生成的一个数据透视简表,现在需要将其数据透视表的名称修改为:汇总数据 解决办法 修改后的效果如下:

  6. Oracle 字段类型

    Oracle 字段类型 http://www.cnblogs.com/lihan/archive/2010/01/06/1640547.html 字段类型 描述 字段长度及其缺省值 CHAR (siz ...

  7. Oracle 中for update和for update nowait的区别

    http://www.cnblogs.com/quanweiru/archive/2012/11/09/2762223.html 1.for update 和 for update nowait 的区 ...

  8. glob (programming) and spool (/var/spool)

    http://en.wikipedia.org/wiki/Glob_(programming) In computer programming, in particular in a Unix-lik ...

  9. ROR部署到Heroku出现Application Error和code=H10 desc=&quot;App crashed“问题

    1.问题发现之前的准备 在读<Learn Python In Hard Way>的时候,发现作者谈到一个非常有趣的事情,在做一些有趣的事情之前做的无聊的事情叫做yak shaving,牦牛 ...

  10. FZU2125:简单的等式

    Problem Description 如今有一个等式例如以下:x^2+s(x,m)x-n=0. 当中s(x,m)表示把x写成m进制时,每一个位数相加的和.如今,在给定n,m的情况下,求出满足等式的最 ...