Flask框架和Flask-Script介绍

一、装饰器decorator

在Python中装饰器,在Java中称为注解;

# -*- encoding=UTF-8

'''
* 用来传递任意个无名字参数,这些参数会一个Tuple的形式访问。
**用来处理传递任意个有名字的参数,这些参数用dict来访问
'''
def log(level, *args, **kvargs):
    def inner(func):
        def wrapper(*args, **kvargs):
            print level, ': before calling ', func.__name__
            print level, ': args:', args, 'kvargs:', kvargs
            func(*args, **kvargs)
            print level, ': after calling ', func.__name__
            print ''
        return wrapper
    return inner

@log(level='INFO')
def hello(name, msg):
    print 'hello', name, msg

if __name__ == '__main__':
    hello(name='nowcoder', msg='i miss you')

输出结果:

INFO : before calling  hello
INFO : args: () kvargs: {'msg': 'i miss you', 'name': 'nowcoder'}
hello nowcoder i miss you
INFO : after calling  hello


二、Flask安装和框架

1 官网

http://flask.pocoo.org

中文版本

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


2 框架

无论是访问Web页面都是一个request;



3 安装

在命令行窗口键入pip install flask;


三、路由routing

1 /结尾自动补齐???

2 多映射

@app.route('/')

@app.route('/index/')

3 参数变量

@app.route('/index/<uid>')

4 变量类型

@app.route('/index/<int:uid>')


举例:

# 导入flask模块的Flask类
from flask import Flask

# 定义一个应用,一个网站就是一个应用
app = Flask(__name__)

# 指定一个路径的映射
@app.route('/')
def index():
	return 'hello'

# 多映射
@app.route('/')
@app.route('/index')
def index():
	return 'hello'	
	
# 传递传参数变量<>
@app.route('/profile/<uid>')
def profile(uid):
	return 'profile: ' + uid

# 转化profile/后接收的数据类型
@app.route('/profile/<int:uid>')
def profile(uid):
	return 'profile: ' + uid

if __name__ =='__main__':
	# 运行,开启debug模式
	app.run(debug=True) 


四、HTTP Method

一般网站只用GET和POST,代表获取和更新;

HTML的form只支持GET和POST;

1 GET

获取接口信息;

2 HEAD

紧急查看接口HTTP的头;

3 POST

提交数据到服务器;

4 PUT(少用)

支持幂等性的POST;

5 DELETE(少用)

删除服务器上的资源;

6 OPTIONS(少用)

查看支持的方法;

补充:

在Chrome浏览器上安装Postman,用于捕获HTTP请求;

使某方法支持POST,则需显式指定;

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


五、静态和模板文件

1 静态

默认目录:static/templates

文件:css/js/images


2 模板

默认目录:templates

文件::*.html,*.htm


六、Jinja2

1 模板语法

{{变量/表达式}}

{%语法%}

{#注释#}

#开头,行语法表达式:app.jinja_env.line_statement_prefix = '#'

2 语法

2.1 for

loop.index,loop.index0
loop.first,loop.cycle
{% for color in colors: %}
color{{ loop.index }}:{{color}}<br>
{% endfor %}

2.2 filter

默认目录:templates

文件:*.html,*.htm

2.3 模板继承

include

extends

2.4 call/macro

{% macro render_color(color) -%}
<div>This is color: {{color}}
{{ caller() }}</div>
{%- endmacro %}

{% for color in colors: %}
{% call render_color(color) %}
render_color_demo
{% endcall %}
{% endfor %} 


七、requsts和response

导入request和make_response;

1 request对象

method:当前请求方法(POST,GET等)

url:当前链接地址

path:当前链接的路径

environ:潜在的WSGI环境

headers:传入的请求头作为字典类对象

data:包含传入的请求数据作为

args:请求链接中的参数(GET参数),解析后

form:form提交中的参数,解析后

values:args和forms的集合

json:json格式的body数据,解析后

cookies:cookie读取


2 response对象

2.1 生成response对象

response = make_response(render_template(index.html))

2.2 方法

status:响应状态

headers:响应头,设置http字段

set_coockie:设置一个cookie


举例:

#-*-coding:utf8-*-
from flask import Flask, flash, request, make_response

app = Flask(__name__)
app.jinja_env.line_statement_prefix = '#'
app.secret_key = '123'

@app.route('/request')
def requestdemo():
    key = request.args.get('key', 'defaultkey')

    res = request.args.get('key', 'defaultkey')+'<br>'
    res+= request.url+'<br>'+request.path+'<br>'

    response=make_response(res)
    response.set_cookie('rainbow', key)
    response.headers['rainbow'] = 'twc' # 在Chrome浏览器的检查中网络的Headers可以查看到
    return response

if __name__ == '__main__':
    app.run(debug=True)


八、重定向和错误

导入redirect方法;

1 重定向

redirect(location, code)

其中,location是链接路径,code取值有301和302,301——永久转移,302——临时转移;

#-*-coding:utf8-*-
from flask import Flask, flash, redirect

app = Flask(__name__)
app.jinja_env.line_statement_prefix = '#'
app.secret_key = '123'

@app.route('/newpath')
def newpath():
    return 'newpath'

@app.route('/re/<int:code>')
def redirect_demo(code):
    return redirect('/newpath', code=code)

if __name__ == '__main__':
    app.run(debug=True)



2 error

默认情况下,每个错误代码会显示一个黑白错误页面,但用户体验不好;

若要定制错误页面,可以使用 errorhandler() 装饰器;

创建一个404.html文件用于定制的错误页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>你要找的页面去火星了</title>
</head>
<body>
    <h2>抱歉,该页面不存在</h2>
</body>
</html>

在程序中使用errorhandler()装饰器进行错误页面捕获;

#-*-coding:utf8-*-
from flask import Flask, flash, render_template

app = Flask(__name__)
app.jinja_env.line_statement_prefix = '#'
app.secret_key = '123'

@app.errorhandler(404)
def not_found(e):
    return render_template('404.html')

if __name__ == '__main__':
    app.run(debug=True)



九、Flash Message

Flask提供消息闪现机制,方便在应用中消息提示;

首先导入flash方法,再对secret_key进行赋值,以对消息加密;

然后定义一个路由,使用flash(msg)方法,并返回模板;

flaskApp.py代码如下,功能是对输入的用户名和密码进行相应提示;

#-*-coding:utf8-*-  
from flask import Flask, flash, render_template,request  
  
app = Flask(__name__)  
app.secret_key = '123'  
 
@app.route('/')  
def hello_user():  
    flash("Welcomt to China")  
    return render_template("index.html")  
 
@app.route('/login', methods=['POST'])  
def login():  
    form=request.form  
    username=form.get('username')  
    password=form.get('password')  
    if not username:  
        flash("Please enter username")  
        return render_template("index.html")  
    if not password:  
        flash("Please enter password")  
        return render_template("index.html")  
    if username=="wencheng" and password=="123":  
        flash("Login succeed")  
        return render_template("index.html")  
    else:  
        flash("Username or password is not correcct")  
        return render_template("index.html")  
  
if __name__ == '__main__':  
    app.run()

index.html文件代码如下,get_flashed_messages从python程序获取传递的信息,呈现给用户的样式在这里指定;

<!DOCTYPE html>  
<html>  
    <head lang="en">  
        <meta charset="UTF-8">  
        <title></title>  
    </head>  
    <body>  
        <h1>Hello Login</h1>  
        <!--  
        form标签的action属性是指提交表单时将数据提交到指定页面,这里是/login页面  
        form标签的method属性是规定如何发送表单数据,有post/get  
        -->  
        <form action="/login" method="post">  
            <input type="text" name="username">  
            <input type="password" name="password">  
            <input type="submit" name="submit">  
        </form>  
        <h3>{{get_flashed_messages()[0]}}</h3>  
    </body>  
</html>  


十、Log

1 logging

1.1 Logger对象

setLevel(lvl) 设置logger级别

其中,lvl可取值为logging.NOTSET(0)、logging.DEBUG(10)、logging.INFO(20)、logging.WARNING(30)、logging.ERROR(40)、logging.CRITICAL(50);

debug(msg) 记录DEBUG级别以上的日志

其中,msg是字符串;

info(msg) 记录INFO级别以上的日志

warning(msg) 记录WARNING级别以上的日志

error(msg) 记录ERROR级别以上的日志

critical(msg) 记录CRITICAL级别以上的日志

log(lvl, msg) 记录指定整数值代表的日志级别以上的日志


1.2 Handler对象

setLevel(lvl) 设置handler级别

setFormatter(form) 设置日志输出形式

其中,form是logging.Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]')

debug(msg) 记录DEBUG级别以上的日志

info(msg) 记录INFO级别以上的日志

warning(msg) 记录WARNING级别以上的日志

error(msg) 记录ERROR级别以上的日志

critical(msg) 记录CRITICAL级别以上的日志

log(lvl, msg) 记录指定整数值代表的日志级别以上的日志


1.3 模块级方法looging

basicConfig(level=logging.DEBUG,

format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',

datefmt='%a, %d %b %Y %H:%M:%S',

filename='license.log',

filemode='w') 配置logging系统

debug(msg) 记录DEBUG级别以上的日志

info(msg) 记录INFO级别以上的日志

warning(msg) 记录WARNING级别以上的日志

error(msg) 记录ERROR级别以上的日志

critical(msg) 记录CRITICAL级别以上的日志

log(lvl, msg) 记录指定整数值代表的日志级别以上的日志


2 flask-logging

2.1 logging to a file

RotatingFileHandler(path) 将日志文件中的文本进行回滚处理

其中,path指定日志存放路径及日志文件名;

FileHandler(path) 将错误信息加入到一个文件中


举例:

#-*-coding:utf8-*-
from flask import Flask
import logging
from logging.handlers import RotatingFileHandler

app = Flask(__name__)
app.jinja_env.line_statement_prefix = '#'
app.secret_key = '123'

@app.route('/log/<level>/<msg>')
def log(level, msg):
    dict = {'warn': logging.WARN, 'error':logging.ERROR, 'info': logging.INFO}
    if(dict.has_key(level)):
        app.logger.log(dict[level], msg)
    return 'logged:' + msg

def set_logger():
    # RotatingFileHandler将日志文件中的文本资料进行回滚处理
    info_file_handler = RotatingFileHandler('F:\\logs\\info.txt')
    info_file_handler.setLevel(logging.INFO)
    app.logger.addHandler(info_file_handler)

    warn_file_handler = RotatingFileHandler('F:\\logs\\warn.txt')
    warn_file_handler.setLevel(logging.WARN)
    # logger.hanlder(hdlr)增加一个指定的处理器hdlr到该logger
    app.logger.addHandler(warn_file_handler)

    error_file_handler = RotatingFileHandler('F:\\logs\\error.txt')
    error_file_handler.setLevel(logging.ERROR)
    app.logger.addHandler(error_file_handler)

if __name__ == '__main__':
    set_logger()
    app.run(debug=True)


2.2 error mail

在debug模式为‘false’的服务器上,通过引入logging库文件,引入处理类 SMTPHander,当服务器中的app发生了错误报告时,会通过其设置的邮箱地址来将app的后天错误信息发送到指定的server-error@example.com 邮箱中,提醒管理员后台出现错误信息,及时对错误信息进行处理;

举例:

from flask import Flask
import logging
from logging.handlers import SMTPHandler

app = Flask(__name__)
app.jinja_env.line_statement_prefix = '#'
app.secret_key = '123'

@app.route('/index/<level>')
def log(level):
	if(level == logging.ERROR or level == logging.CRITICAL)
		app.logger.addHandler(mail_handler)
	
def set_logger():
	ADMINS = ['yourname@example.com']
	mail_handler = SMTPHandler('127.0.0.1',
				   'server-error@example.com',
				   ADMINS, 'YourApplication Failed')
	mail_handler.setLevel(logging.ERROR)

if '__name__' == '__main__':
	set_logger()
	app.run(debug = True)


十一、flask-script

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

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

官方文档:http://flask-script.readthedocs.io/en/latest/

1 创建并运行命令

首先,创建一个Python模板运行命令脚本,可起名为manager.py;

在该文件中,必须有一个Manager实例,Manager类追踪所有在命令行中调用的命令和处理过程的调用运行情况;

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

调用manager.run()启动Manager实例接收命令行中的命令;

#-*-coding:utf8-*-
from flask_script import Manager
from debug import app

manager = Manager(app)

if __name__ == '__main__':
    manager.run()

其次,创建并加入命令;

有三种方法创建命令,即创建Command子类、使用@command修饰符、使用@option修饰符;

第一种——创建Command子类

Command子类必须定义一个run方法;

举例:创建Hello命令,并将Hello命令加入Manager实例;

#-*-coding:utf8-*-
from flask_script import Manager
from flask_script import Command
from debug import app

manager = Manager(app)

class Hello(Command):
    'hello world'
    def run(self):
        print 'hello world'

manager.add_command('hello', Hello())

if __name__ == '__main__':
    manager.run()

执行如下命令:

python manager.py hello
> hello world


第二种——使用Command实例的@command修饰符

#-*-coding:utf8-*-
from flask_script import Manager
from debug import app

manager = Manager(app)

@manager.command
def hello():
    'hello world'
    print 'hello world'

if __name__ == '__main__':
    manager.run()

该方法创建命令的运行方式和Command类创建的运行方式相同;

python manager.py hello
> hello world


第三种——使用Command实例的@option修饰符

复杂情况下,建议使用@option;

可以有多个@option选项参数;

#-*-coding:utf8-*-
from flask_script import Manager
from debug import app

manager = Manager(app)

@manager.option('-n', '--name', dest='name', help='Your name', default='world')
@manager.option('-u', '--url', dest='url', default='www.csdn.com')
def hello(name, url):
    'hello world or hello <setting name>'
    print 'hello', name
    print url

if __name__ == '__main__':
    manager.run()

运行方式如下:

python manager.py hello
>hello world
>www.csdn.com

python manager.py hello -n sissiy -u www.sissiy.com
> hello sissiy
>www.sissiy.com


  • 10
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值