Flask应用程序

一个简单的Flask应用程序

# 导入flask程序
from flask import Flask # 初始化flask对象
app = Flask(__name__)
# 装饰器模式,新建路由,绑定index视图函数
@app.route("/index")
def index():
return "index page" # 判断当前的__name__ 是否是__main__
# __name__ : 如果做为单一模块运行,表示主模块名称:__main__
# 如果做为模块导入,那么就表示当前模块的名字
if __name__ == '__main__':
# 启动app
app.run()

运行之后,在浏览器地址栏输入:http://127.0.0.1:5000/index

就可以看到视图函数返回的内容

Flask程序创建的参数

Flask程序创建(app = Flask(初始化参数)的时候其实有很多的参数,前面提到的例子中只写了:__name__。下面会详细说下创建的参数。

源码中的参数是:

这里我只介绍常用的

import_name

# 第⼀一个参数:指定当前应⽤用程序所处于的模块,其可以决定静态⽂文件从哪个位置开始查找,
# 在加载静态⽂文件时,会从第⼀一个参数指定的模块下开始查找,
# 如果模块不不存在,会从当前app所在模块的⽬目录下开始找'static'⽂文件夹
# 多数人在这个地方传入__name__。所以默认是__main__,因为不存在__main__模块,所以会从当前模块的同级目录查找static文件夹

static_url_path

静态文件访问路径

static_folder

静态文件所处文件夹

template_folder

模板文件所处文件夹

默认是:templates

程序运行时的参数

app.run("运行参数")

运行参数:
debug   # 表示启用debug模式
host    # 运行的地址
port    # 绑定的端口

Flask项目加载配置

从对象中加载配置

from flask import Flask

app = Flask(__name__)

class Config(object):
# 开启调试模式
DEBUG = True # 设置debug开启,当出错会在网页中显示出来。
NAME = "name" # 设置一个自定义的变量 # 从对象当中加载
app.config.from_object(Config) @app.route("/")
def index():
# a = 1 / 0
print(app.config.get("NAME")) # 读取自定义的变量
return "index page" if __name__ == '__main__':
app.run()

从路径中加载配置

首先要在当前目录建一个文件,文件名和后缀可以任意取,但是本着见名知意的原则,我取名为了:config.cfg,在文件中我写入了:DEBUG = True

from flask import Flask

app = Flask(__name__)

app.config.from_pyfile("config.cfg")

@app.route("/")
def index():
# a = 1 / 0
return "index page" if __name__ == '__main__':
app.run()

其他方法

app.config['DEBUG'] = True
app.DEBUG = True
app.run(debug = True)

返回状态码、抛出和捕捉异常

返回状态码

编码:

@app.route("/")
def index():
return "状态码", 666

效果

自定义相应头

编码:

@app.route("/")
def index():
return "状态码", 666, {"name": "zhangshan"}

效果:

抛出异常

编码:

# 导入包
from flask import abort

效果:

捕获异常

编码:

from flask import Flask, abort

app = Flask(__name__)

@app.errorhandler(404)      # 除了404,这些状态码,也可以对指定的错误进行捕获和处理,比如zeroDivisionError
def demo2(e):
"""专⻔门捕获指定的状态码异常信息,然后处理理异常"""
print(e)
return '服务器器搬家了了' @app.route('/index')
def index():
abort(404) if __name__ == '__main__':
app.run()

效果:

Flask路由

请求方法

限定请求方法

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

获取请求方法

首先要导入request模块,里面封装着用户请求

from flask import request 

然后通过request.method可以获取请求方法。

其他通过request获取的

from flask import Flask
from flask import request app = Flask(__name__) @app.route("/index",methods=["GET","POST"])
def index():
# request : 封装的所有的请求信息
# request.form : 提取表单数据
name = request.form.get("name")
age = request.form.get("age")
# request.args :提取?后面的数据
city = request.args.get("city")
# request.data:提取的是原始数据(json)
print("request.data = %s" % request.data.decode())
return "name = %s,age = %s,city = %s" % (name, age, city) if __name__ == '__main__':
app.run()

默认请求方法

HEAD:获取相应头信息

GET:获取数据,全部信息

OPTIONS:查看某个url可以支持哪些请求方法。

url_map

url_map又可以称为路由视图关系映射,可以通过app.url_map查看。

当同一个路由映射两个视图,当发送请求时,路由会根据map表的顺序从上到下查找,会执行先定义的路由和视图

获取路由的参数

from flask import Flask

app = Flask(__name__)

@app.route('/index/<id>')
def index(id):
return "id: %s" % id if __name__ == '__main__':
app.run(debug=True)

重定向

首先引入模块:

from flask import redirect

重定向到指定网址

 return redirect(‘http://www.baidu.com’)) 

重定向到指定视图

return redirect(url_for("index"))  # url_for需要导包

重定向传参

return redirect(url_for("order", id=11))
from flask import Flask, redirect, url_for

app = Flask(__name__)

@app.route("/order/<id>")
def order(id):
return "id:%s" % id @app.route('/')
def demo():
return redirect(url_for("order", id=11)) # 相当于重定向到指定视图对应的url,而且路由中必须有和其匹配的,否则会报错 if __name__ == '__main__':
app.run()

自定义路由匹配转换器

首先导入模块

 from werkzeug.routing import BaseConverter

下面是自带的转换器,Ctrl+鼠标左键点BaseConverter可以看到默认的转换器

DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}

实际中我们需要这个转换器帮我们做更多的筛选。所以需要自定义。

例子:

from flask import Flask
from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter):
"""⾃自定义转换器器:实现最多传⼊入5个数字""" # 重写⽗父类的属性,定义转换器规则
regex = '[0-9]{5}' app = Flask(__name__) # 将自定义的转换器添加到转换器列表中
app.url_map.converters['re'] = RegexConverter @app.route('/order/<re:order_id>')
def demo1(order_id):
return 'demo1 %s' % order_id if __name__ == '__main__':
app.run()

上面例子中写的太死,下面是优化了的:

from flask import Flask
from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter):
def __init__(self, url_map, *args): # 在启动服务器的时候flask就自动的将正则放入了args中了,等浏览器输入会放入url_map中
super(RegexConverter, self).__init__(url_map)
self.regex = args[0] app = Flask(__name__) # 将自定义的转换器添加到转换器列表中
app.url_map.converters['re'] = RegexConverter @app.route('/order/<re("[0-9]{5}"):order_id>')
def demo1(order_id):
return 'demo1 %s' % order_id if __name__ == '__main__':
app.run()

返回JSON

json模块

json_dict = {
‘name’:’zxc’,
‘age’:18
}
from flask import Flask, json
json_str = json.dumps(json_dict)

这个成json后,传浏览器的时候Content-Type还是text/html,还需要再修改,不建议

jsonify模块

json_dict = {
‘name’:’zxc’,
‘age’:18
}
from flask import Flask, jsonify
json_str = jsonify(json_dict)

这个转json后,浏览器传输的时候Content-Type变成了application/json。建议使用

请求对象属性

data:读取请求体中的原始字符串,比如json字符串

form:用户通过表单发给服务器的数据,比如POST表单数据到服务器

args:用户通过查询参数发给服务器的数据,也就是url中?后面的参数。比如:http://127.0.0.1/upload?name=lisi中的name=lisi

cookies:用户发送给服务器的cookie数据

headers:请求头信息

method:请求方法

url:请求地址

files:用户发送给服务器的文件信息,比如:文件上传时信息

补充:服务器接收用户上传文件:

pic = request.files.get("pic")
pic.save("./123.jpg")

请求勾子

使用装饰器实现监听请求和响应过程

@app.before_first_request

说明:在服务器第一次收到请求前调用,可以做一些初始化,而且只会执行一次,比如连接到数据库

@app.before_request

说明:在请求之前执行

@app.after_request

说明:在请求之后执行

@app.teardown_request

说明:”after_request”和”teardown_request”会在请求处理完成后被调用。区别是”after_request”只会在请求正常退出时才会被调用,它必须传入一个参数来接受响应对象,并返回一个响应对象,一般用来统一修改响应的内容。而”teardown_request”在任何情况下都会被调用,它必须传入一个参数来接受异常对象,一般用来统一释放请求所占有的资源。

以上所以的例子:

from flask import Flask, g, request

app = Flask(__name__)

@app.before_request
def before_request():
print 'before request started'
print request.url @app.before_request
def before_request2():
print 'before request started 2'
print request.url
g.name="SampleApp" @app.after_request
def after_request(response):
print 'after request finished'
print request.url
response.headers['key'] = 'value'
return response @app.teardown_request
def teardown_request(exception):
print 'teardown request'
print request.url @app.route('/')
def index():
return 'Hello, %s!' % g.name if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)

访问”http://localhost:5000/”后,会在控制台输出:

before request started
http://localhost:5000/
before request started 2
http://localhost:5000/
after request finished
http://localhost:5000/
teardown request
http://localhost:5000/

状态保持

cookie

cookie是通过响应将cookie写入到浏览器的

在flask中,先要设置cookie,首先要“做”一个响应

response = make_response('') # make_response这个包需要导入

设置cookie

response.set_cookie('name','zxc')
response.set_cookie('age', '', max_age=3600)

读取cookie

 request.cookies.get('name') 

删除cookie

response.delete_cookie('name')

session

导入模块:

from flask import Flask, session 

加盐:

app.config['SECRET_KEY'] = 'fasf'   # 加盐是让你的原始数据加上这个你随意写入的(一般要用个加密算法得出的结果)的数据再加密,确保数据的安全性

设置session

 session['name'] = 'zxc'

读取session

name = session.get(‘name’)
name = session['name']

删除session

 session.pop('name')

设置session过期时间:

# 过期时间, 通过cookie实现的
from datetime import timedelta
session.permanent = True # 默认是31天
app.permanent_session_lifetime = timedelta(minutes=5) # 指定session具体的过期时间

注意:无论是cookie还是sesion都是存储在浏览器的一个文件中作为状态保持的,而实际应用中,是将私密信息放到服务器的。用Flask中封装的flask_session中的Session来处理,这个会在你的本地和服务器都存储,看你怎么取。

Flask_Script

Flask中的脚本扩展工具包,再开发中我们可以用pycharm来运行,但是部署到服务器就没有pycharm来启动了,需要这些脚本工具

使用步骤

导入模块

from flask_script import Manager 

创建脚本管理对象

 manager = Manager(app) 

使用脚本管理器对象启动程序

 manager.run() 

再终端上执行脚本命令

python demo.py runserver -p 5001 -d    # -d是开启调试模式

添加脚本

Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell,设置数据库的脚本,cronjobs,及其他运行在web应用之外的命令行任务;使得脚本和系统分开;

Flask Script和Flask本身的工作方式类似,只需定义和添加从命令行中被Manager实例调用的命令;

Manager只有一个参数——Flask实例,也可以是一个函数或其他的返回Flask实例;

编码

@manager.command
def test_custom_script():
print u'这⾥里里实在测试⾃自定义脚本,实现⾃自⼰己的逻辑'

使用

初始化:(venv)  python manage.py db init 这个命令会在项目下创建 migrations 文件夹,所有迁移脚本都存放其中。
创建第一个版本:(venv) $ python manage.py db migrate -m "initial migration" 检查migrations\versions,会新建一个版本.py,检查里面表格及字段
运行升级 (venv) $ python manage.py db upgrade,会把项目使用的数据库文件,更新为新的表格、字段,同时保留数据

详细的看:http://www.codeweblog.com/flask%E6%89%A9%E5%B1%95flask-script%E6%96%87%E6%A1%A3%E4%B8%AD%E6%96%87%E7%BF%BB%E8%AF%91/

最新文章

  1. JavaIO学习笔记(五)
  2. This Node源码分析
  3. 回文字算法(java版本)
  4. ccc 使用let
  5. H5页面左图右边文字如何布局
  6. 初识HTTP协议
  7. 再来,LVS+KEEPALIVED
  8. PHP学习笔记七【函数】
  9. Hbase Scan的方法
  10. bzoj1227 组合数学+bit
  11. [Swift]LeetCode85. 最大矩形 | Maximal Rectangle
  12. matplotlib 命令行画图保存
  13. Linux基础(五) Shell函数
  14. linux中DHCP服务配置文件/etc/dhcpd.conf详细说明
  15. mips32和x86下的大小端模式判定
  16. BZOJ 1758 【WC2010】 重建计划
  17. Mac OS 10.12 - 安装JAVA!
  18. CXGRID用法(取行、列值;定位选中某行等等)
  19. c++11 继承控制:final和override
  20. Spark Shuffle(二)Executor、Driver之间Shuffle结果消息传递、追踪(转载)

热门文章

  1. HDU 3499【最短路】
  2. IT兄弟连 JavaWeb教程 Servlet会话跟踪 获取Session对象
  3. 关于如何隐藏UITabbar的问题
  4. Trie树(小)总结 By cellur925
  5. 茅台【思维/数学/剪枝】By cellur925
  6. bzoj1139:[POI2009]Wie
  7. 黑马函数式接口学习 Stream流 函数式接口 Lambda表达式 方法引用
  8. socketserver+socket实现较为复杂的ftp,支持多用户在线
  9. (bzoj1337 || 洛谷P1742 最小圆覆盖 )|| (bzoj2823 || 洛谷P2533 [AHOI2012]信号塔)
  10. MySQL之select简单使用