# 路由转换器: 对路由的内容进行匹配
# any: 括号内填入的字符串才能匹配
# @app.route('/<any(about, help, imprint, class, "foo,bar"):page_name>')
# def index(page_name):
# return 'page_name: %s' % page_name
# path: 跟默认很像, 能过滤斜杠/
# @app.route('/<path:wikipage>')
# def index(wikipage):
# return 'wikipage: %s' % wikipage
重点
自定义正则路由转换器
定义一个工具类继承BaseConverter类
重写__init__方法,添加一个参数
然后再继承基类
增加一个参数
覆盖父类
app.url_map.converters['re'] =RegexConverter
#存放着所有路由转换器 字典里面添加路由 、
匹配所需要的正则
@app.route('/user/<re(r"[a-z]{3}"):user_id>')
def hello_itheima(user_id):
return 'hello: %s'%user_id
class RegexConverter(BaseConverter):
# 2.1 重写init, 提供参数
# regex r"[a-z]{3}"
def __init__(self, url_map, regex):
# 2.2 调用父类方法, 如果不调用, 父类原先的方法可能会丢失
super(RegexConverter, self).__init__(url_map)
# 2.3 修改父类的regex属性
self.regex = regex
-------------------------------------
异常捕获
@app.route('/')
def index():
# 正在处理用户的请求, 但是遇到了一些异常问题, 需要服务器主动抛出异常
abort(403)
return 'hello flask'
@app.errorhandler(404)
def page_not_found(error):
return '服务器炸了', 404
可以捕获错误码 也可以捕获异常
视图函数需要接受错误, 但不需要显示
# BaseException: 可以捕获所有的异常
@app.errorhandler(BaseException)
def special_exception_handler(error):
# 最好内部做好if判断, 因为不是所有异常都是500错误
return '0不能做除数' , 500
---------------------------------------------------
钩子——————中间人
"""
before_first_request:在处理第一个请求前运行。
before_request:在每次请求前运行。
after_request:如果没有未处理的异常抛出,在每次请求后运行。
teardown_request:在每次请求后运行,即使有未处理的异常抛出。
"""
@app.route('/')
def index():
# 视图函数需要紧跟着路由, 这样就可以实现绑定. (路由和视图函数的映射关系就绑定了)
print '视图函数任务处理中'
return 'hello flask'
@app.before_first_request
def before_first_request():
print 'before_first_request'
@app.before_request
def before_request():
print 'before_request'
# return 'hehe'
@app.after_request
def after_request(response):
print 'after_request'
# 如果这么处理, 那么json.dumps也可以实现和jsoninf同样的效果
# response.headers['Content-Type'] = 'application/json'
return response
@app.teardown_request
def teardown_request(error):
print 'teardown_request % s' % error
--------------------------------------------------
设置cookie
需要导入make_response
@app.route('/set_cookie')
def set_cookie():
response = make_response('set_cookie')
# 设置cookie
response.set_cookie('name', 'itheima', max_age=3600)
return response
读取cookie
需要导入request
@app.route('/get_cookie')
def get_cookie():
# 读取cookie
print request.cookies.get('name')
return 'get_cookie'
删除cookie
需要导入make_response
@app.route('/delete_cookie')
def delete_cookie():
response = make_response('delete_cookie')
response.delete_cookie('name')
return response
-------------------------------------------------
设置session
flask把session数据以加密的形式存到cookie里面
首先设置秘钥,用于加密session(重点)
app.config['SECRET_KEY'] = '任意字母组合'
设置session,导入session模块
@app.route('/set_session')
def set_session():
session['name'] = 'itcast'
return 'set_session'
获取session
@app.route('/get_session')
def get_session():
return session.get('name')
-----------------------------------------------------
falsk里面的命令行也可启动程序
首先导入 from flask_script import Manager
第二步 进行创建 需要导入app
manager = Manager(app)
第三步 把app.run()改为 manager.run()
启动方式和django一样 在终端输入
python py文件名 runserver
后面可以加参数 -d 为debug
-p为修改端口
-p为修改ip
还可加 app.debug = True
用途 比如迁移数据库
-------------------------------------------------------
flask模板的应用
Flask提供的 render_template 函数封装了该模板引擎
# -*- coding:utf-8 -*-
# -*- coding:utf-8 -*-
# Flask是基于python2.7运行的
# 1. 导入Flask扩展
from flask import Flask,render_template
# from
# 2. 创建Flask应用程序实例对象
# 暂时认为, 固定要传__name__
app = Flask(__name__)
# 3. 定义路由及视图函数
# 127.0.0.1:5000/ --> hello flask
# Flask中路由的实现, 是通过装饰器实现的
@app.route('/')
def index():
my_list = [1,2,3]
my_dict = {
'name':'itheima',
'password':'666'
}
my_int = 1,23,4
# 视图函数需要紧跟着路由, 这样就可以实现绑定. (路由和视图函数的映射关系就绑定了)
return render_template('index1.html',my_list=my_list,my_dict = my_dict,my_int = my_int)
# 4. 运行
if __name__ == '__main__':
# 类似与runserver, 也是一个Flask自带的简易服务器
app.run(port=5003)
templates里面的代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>随便写点东西算了</h1>
<hr>
{{ my_list }}
<hr>
{{ my_dict }}
<hr>
{{ my_int }}
<hr>
</body>
</html>
----------------------------------------------
模板里面过滤器的使用
在py文件中创建 列表字典==
html页面接收参数
过滤器的使用方式为:变量名 | 过滤器。
{{variable | filter_name(*args)}}
如果没有任何参数传给过滤器,则可以把括号省略掉
{{variable | filter_name}}
如:``,这个过滤器的作用:把变量variable 的值的首字母转换为大写,其他字母转换为小写
链式调用
在 jinja2 中,过滤器是可以支持(链式调用)的,示例如下:
{{ "hello world" | reverse | upper }}
常见内建过滤器
字符串操作
safe:禁用转义
<p>{{ '<em>hello</em>' | safe }}</p>
capitalize:把变量值的首字母转成大写,其余字母转小写
<p>{{ 'hello' | capitalize }}</p>
lower:把值转成小写
<p>{{ 'HELLO' | lower }}</p>
upper:把值转成大写
<p>{{ 'hello' | upper }}</p>
title:把值中的每个单词的首字母都转成大写
<p>{{ 'hello' | title }}</p>
reverse:字符串反转
<p>{{ 'olleh' | reverse }}</p>
format:格式化输出
<p>{{ '%s is %d' | format('name',17) }}</p>
striptags:渲染之前把值中所有的HTML标签都删掉
<p>{{ '<em>hello</em>' | striptags }}</p>
truncate: 字符串截断
<p>{{ 'hello every one' | truncate(9)}}</p>
列表操作
first:取第一个元素
<p>{{ [1,2,3,4,5,6] | first }}</p>
last:取最后一个元素
<p>{{ [1,2,3,4,5,6] | last }}</p>
length:获取列表长度
<p>{{ [1,2,3,4,5,6] | length }}</p>
sum:列表求和
<p>{{ [1,2,3,4,5,6] | sum }}</p>
sort:列表排序
<p>{{ [6,2,3,1,5,4] | sort }}</p>
语句块过滤
{% filter upper %}
一大堆文字
{% endfilter %}
自定义过滤器
do开头 参考底层代码
方式一
通过调用应用程序实例的add_template_filter方法实现自定义过滤器。该方法第一个参数是函数名,第二个参数是自定义的过滤器名称:
def do_list_reverse(list):
list.reverse()
return list
app.add_template_filter(do_list_reverse, 'lsreverse')
方式二
用装饰器来实现自定义过滤器。装饰器传入的参数是自定义的过滤器名称。
@app.template_filter('lsreverse')
def do_list_reverse(list):
list.reverse()
return list
控制代码块
if语句
Jinja2 语法中的if语句跟 Python 中的 if 语句相似,后面的布尔值或返回布尔值的表达式将决定代码中的哪个流程会被执行:
{%if user.is_logged_in() %}
<a href='/logout'>Logout</a>
{% else %}
<a href='/login'>Login</a>
{% endif %}
过滤器可以被用在 if 语句中:
{% if comments | length > 0 %}
There are {{ comments | length }} comments
{% else %}
There are no comments
{% endif %}
循环
我们可以在 Jinja2 中使用循环来迭代任何列表或者生成器函数
{% for num in my_list %}
{% if num > 3 %}
{{ num }}
{% endif %} <br>
{% endfor %}
循环和if语句可以组合使用
{% for num in my_list if num > 3 %}
{{ num }} <br>
{% endfor %}
在一个 for 循环块中你可以访问这些特殊的变量:
变量 描述
loop.index 当前循环迭代的次数(从 1 开始)
loop.index0 当前循环迭代的次数(从 0 开始)
loop.revindex 到循环结束需要迭代的次数(从 1 开始)
loop.revindex0 到循环结束需要迭代的次数(从 0 开始)
loop.first 如果是第一次迭代,为 True 。
loop.last 如果是最后一次迭代,为 True 。
loop.length 序列中的项目数。
loop.cycle 在一串序列间期取值的辅助函数。见下面示例程序。
在循环内部,你可以使用一个叫做loop的特殊变量来获得关于for循环的一些信息
比如:要是我们想知道当前被迭代的元素序号,则可以使用loop变量的index属性,例如:
{% for num in my_list %}
{{ loop.index }} -
{% if num > 3 %}
{{ num }}
{% endif %} <br>
{% endfor %}
假设my_list=[1, 3, 5, 7, 9]会输出这样的结果
1-
2-
3-5
4-7
5-9
cycle函数会在每次循环的时候,返回其参数中的下一个元素,可以拿上面的例子来说明:
{% for num in my_list %}
{{ loop.cycle('a', 'b') }} -
{{ num }} <br>
{% endfor %}
会输出这样的结果:
a-
b-
a-5
b-7
a-9
可以在循环的开始和结束位置放置一个 - 号去除for循环不换行情况下产生的空格
{% for num in my_list -%}
{{ num }}
{%- endfor %}
------------------------------------------------------------
模板代码的复用
继承与重写
{% extends 'mobanwenjian.html' %}
{% block center %}
重写后的中间内容 <br>
{# {{ super() }}<br>#}
{% endblock %}
二. 包含
Jinja2模板中,包含(Include)的功能是将另一个模板整个加载到当前模板中,并直接渲染。
include的使用
{% include 'hello.html' %}
包含在使用时,如果包含的模板文件不存在时,程序会抛出TemplateNotFound异常,可以加上 ignore missing 关键字。如果包含的模板文件不存在,会忽略这条include语句。
include的使用加上关键字ignore missing
{% include 'hello.html' ignore missing %}
定义宏
<form>
<label>用户名:</label><input type="text" name="username"><br>
<label>昵称:</label><input type="text" name="nickname"><br>
<label>身份证:</label><input type="text" name="idcard"><br>
<label>密码:</label><input type="password" name="password"><br>
<label>确认密码:</label><input type="password" name="password2"><br>
<input type="submit" value="提交">
</form>
1.定义一个macro函数
{#{% macro input(label="", type="text", name="", value="")%}#}
{# 可以提出公用的代码, 预留出要动态传入的参数值#}
{# <label>{{ label }}</label><input type="{{ type }}" name="{{ name }}" value="{{ value }}"><br>#}
{#{% endmacro %}#}
2.在别的文件定义好
{#def 函数名(参数)#}
{% macro input(label="", type="text", name="", value="")%}
{# 可以提出公用的代码, 预留出要动态传入的参数值#}
<label>{{ label }}</label><input type="{{ type }}" name="{{ name }}" value="{{ value }}"><br>
{% endmacro %}
{% macro input2(label="", type="text", name="", value="")%}
<label>{{ label }}</label><input type="{{ type }}" name="{{ name }}" value="{{ value }}"><br>
{% endmacro %}
3.导入
{% import 'basic_mcaro.html' as func%}
用func.函数名来替代
<form>
{{ func.input2('用户名:', name="username") }}
{{ func.input2('昵称:', name="nickname") }}
{{ func.input2('身份证:', name="idcard") }}
{{ func.input2('密码:', type="password", name="password") }}
{{ func.input2('确认密码:', type="password", name="password2") }}
{{ func.input2(type="submit", value="提交") }}
</form>