Flask(二)

钩子函数

from flask  import Flask

app = Flask(__name__)

# 第一次请求之前会来调用

# 初始化操作

@app.before_first_request

def demo1():

      print("第一次请求会调用"")

# 每次请求之前都会调用,应用场景:封装ip处理

@app.before_request

def demo2():

  print("每次请求之前会被调用")

#每次请求之后都会调用这个钩子函数,应用场景:对response进行统一处理

@app.after_request

def demo3(response):

  # response.headers["Content-Type"] = "application/json"

  print("每次请求之后才会调用")

  return response

# 每次都会执行,都会带入一个服务器的错误过来

@app.teardown_request

def demo4(err):

  print(err)

  print("每次请求之后都会调用一个服务器错误过来)

if  __name__ == "_main__":

  app.run(debug=True)

对cookie进行操作:

from flask import Flask, make_response, request

app = Flask(__name__)

@app.route("/login")

def login():

  """登录成功之后借助cookie保存用户登录信息"""

  # 创建响应对象

  response = make_response("login_success")

  # 借助响应对象的set_cookie方法设置键值对

  # 参数1:ke, 参数2:value, 参数3:max_age表示过期时长(以秒为单位)

  # set_cookie("key",值) Cookie是存储在浏览器中的一段纯文本

  response.set_cookie("user_name", "kangkang", max_age=3600)

  response.set_cookie("age", "18", max_age= 3600)

  return response

# 获取cookie

@app.route("/index")

def index():

"""再次请求首页的时候,提起cookie中的用户信息"""

  user_name = request.cookies.get("user_name", "")

  age = request.cookies.get("age", "")

  return "index %s --- %s" %(user_name, age)

# 删除cookie

@app.route("/login_out")

def login_out():

  response = make_response("login_out success")

  response.delete_cookie("user_name")

  response.delete_cookie("age")

  #将响应对象返回

  return response

if __name__== "__main__":

  app.run(debug=True)

对session进行操作,session依赖于cookie,服务器会返回一个session_id即为cookie,session里面包含用户信息

from flask import Flask, session

app = Flask(__name__)

# session需要设置秘钥,可以写一个任意的字符串,两种写法,app.config是个字典

app.config="2323242423"

app.config["SECREY_KEY"] = "3213232"

@app.route("/login")

def login():

  # session将用户数据存储在服务器的内存中--redis数据库

  session["user_name"]= "kangkang"

  session["user_id"] = "12"

  return "login success"

@app.route("/index")

def index():

  user_name = session.get("user_name", "")

  user_id = session.get("user_id", "")

  return "index:%s ---%s" %(user_name, user_id)

@app.route("/login_out")

def login_out():

  session.pop("user_name", "")

  session.pop("age", "")

  return "login_out success"

if __name__ == "__main__":

  app.run(debug=True)

捕获异常:

from flask import Flask, redirect, abort

app = Flask(__name__)

@app.route("/")

def hello():

  a = 1/0

  abort(404)  # 主动产生一个404异常,abort需要先导入该库,abort传入的必须是http存在的错误状态码

  return "hello world"

# 通过errorhandler捕获错误状态码

@app.errorhandler(404)

def handler(e):

  print(e)

  # 重定向到百度的错误页面链接

  return redirect("https://www.baidu.com/search/error.html")

# 通过errorhandler捕获异常

@app.errorhandler(ZeroDivisionError)

def err(err):

  return "不能除以0"

if __name__ == "__main__":

  app.run(debug=True)

上下文:

请求上下文: request和session

应用上下文:current_app, g变量(flask程序全局的一个临时变量)

from flask import Flask, request, session, current_app, g

app =Flask(__name__)

app.config["SECRECT_KEY"] = "avdvdvd"

# print(request.method)  Working outside of request context.请求上下文超出范围

# print(g.user) Working outside of request context.应用上下文超出范围

# 只能在视图函数里面进行操作,在外部进行操作就会超出范围

@app.route("/")

def hello():

# 请求上下文

  print(request.method)

  print(request.url)

  session["user_name"] = "curry"

  print(session.get("user_name", ""))

  # 应用上下文(current_app, g)

  print(current_app.config.get("DEBUG"))

  g.user = "james"

  print(g.user)

  return "hello world"

if __name__ == "__main__":

  app.run(debug=True)

  • 请求上下文:保存了客户端和服务器交互的数据
  • 应用上下文:flask 应用程序运行过程中,保存的一些配置信息,比如程序名、数据库连接、应用信息等

Flask-Script拓展

需要安装Flask-Script拓展

pip install flask-script

from flask import Flask

from flask_script import Manager

app = Flask(__name__)

manager= Manager(app)

@app.route("/")

def hello():

  return "hello world"

if __name__ == "__main__":

  manager.run()

通过终端命令: python XX.py runserver  -h ip地址 -p 端口号  -d

同样也可以配置该文件的环境变量进行右键运行.

Jinja2模板引擎简介

视图函数的主要作用是生成请求的响应,这是最简单的请求。实际上,视图函数有两个作用:处理业务逻辑和返回响应内容。在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本。本节学到的模板,它的作用即是承担视图函数的另一个作用,即返回响应内容。

  • 模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取
  • 使用真实值替换变量,再返回最终得到的字符串,这个过程称为“渲染”
  • Flask是使用 Jinja2 这个模板引擎来渲染模板

使用模板的好处:

视图函数只负责业务逻辑和数据处理(业务逻辑方面)

而模板则取到视图函数的数据结果进行展示(视图展示方面)

代码结构清晰,耦合度低

Jinja2:是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言。

模板语言:是一种被设计来自动生成文档的简单文本格式,在模板语言中,一般都会把一些变量传给模板,替换模板的特定位置上预先定义好的占位变量名

Flask提供的 render_template 函数封装了该模板引擎

render_template 函数的第一个参数是模板的文件名,后面的参数都是键值对,表示模板中变量对应的真实值

{{}}来表示变量名,这种{{}}语法叫做代码块变量, {{{position.title}}

Jinja2模板中的变量代码块可以是任意Python类型或者对象,只要它能够Python的Str()方法转换为一个字符串就可以,

{{your_dict['key']}}

{{your_list[0]}}

用{% %}定义的控制代码块,可以实现一些语言层次的功能,比如循环或if语句

{% if user %}

  {{user}}

{% else %}

  hello!

<ul>

  {% for index in indexs %}

    <li>{{index}}</li>

    {% endfor %}

</ul>

使用{# #}进行注释,注释的内容不会再html中被渲染出来

模板的基本使用:

在项目下创建templates文件夹,用于存放所有的模板文件,并在目录下创建一个模板html文件

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")

def index():

  myint = 18

  mystr = "curry"

  my_list =[1, 23,4,6,5]

  my_dict = {

  "name":"duan",

  "age":28

  }

  return render_template("dem01.html",

             myint = myint, mystr = mystr, my_dict=my_dict, my_list = my_liust)

if __name == "__main__":

  app.run()

对应的demo01.html:

<!DOCTYPE html>

<html lang="en">

<head>

   <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
我的模板html内容
<br/>{{ my_str }}
<br/>{{ my_int }}
<br/>{{ my_array }}
<br/>{{ my_dict }}

</body> </html>

链式调用: {{"hello world" | reverse | upper}}

常见内建过滤器:

字符串操作

safe:禁止转义 {{"<em>hello</em>"| safe}}

capitalize:把变量的首字母转成大写,其余字母小写 {{'hello" | capitalize}}

lower:把值转成小写, {{"HELLO" | lower}}

upper:把值转成大写,{{"hello" | upper}}

title:把每个单词的首字母都转成大写, {{'he is girl" | title}}

reverse:字符串反转,

format:格式化输出 {{'%s is %d' | format('name', 7)}}

striptags:把html中的tag去掉, {{'<h1>hello</h1>" | striptags}}

truncate:字符串截断 {{'hello every one" | truncate(9) }}

列表操作

list=[1,2,3,1,2,3,6,8,4]

first :取第一个元素 {{list | first}}

last:取最后一个元素{{list | last}}

length:获取列表长度{{list | length}}

sum:求列表的和{{list | sum}}

sort:列表排序 {{list | sort}}

语句块过滤:

{% filter upper %}

 # 一大堆文字#

{% endfilter %}

自定义过滤函器

from flask import render_template, Flask

app = Flask(__name__)

# 方法一:自定义列表反函数

@app.template_filter("list_reverse")

def list_rever(list):

  list.reverse()

  return list

# 方式二:将自定义的函数添加到flask过滤器中,add_template_filter(函数名, "创建过滤器名称") 函数名不需要打引号

app.add_template_filter(list_rever, "list_reverse")

@app.route("/")

def index():

  list = [1,2,3,4,6,5]

  return render_template("demo02.html", list = list)

if __name__ == "__main__":

   app.run(debug=True)

demo02.html内容:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
自定义过滤器<hr>
<body>
{{ list }}
<br>
{{ list | list_reverse }}
</body>
</html>

 控制代码:

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")

def index():

  # 只显示四行数据, 并设置颜色

  my_list = [

    

{
"id":1,
"value":"我爱代码"
},
{
"id": 2,
"value": "代码使人快乐"
},
{
"id": 3,
"value": "沉迷于代码无法自拔"
},
{
"id": 4,
"value": "日渐消瘦"
},
{
"id": 5,
"value": "以梦为马,越骑越傻"
}

]

return render_template("demo03.html", my_list = my_list)

if __name__ == "__main__":

  app.run(debug=True)

demo03.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
控制代码块<hr>
{% for item in my_list%}
{# {% if item.id != 5 %}#}
{% if loop.index == 1 %}
<li style="background-color: yellow">{{ item.value }}</li>
{% elif loop.index == 2%}
<li style="background-color: #2aabd2">{{ item.value }}</li>
{% elif loop.index == 3 %}
<li style="background-color: #2b542c">{{ item.value }}</li>
{% elif loop.index == 4 %}
<li style="background-color: #8a6d3b">{{ item.value }}</li>
{% elif loop.index == 5 %}
<li style="background-color: darkgrey">{{ item.value }}</li>

{% endif %}

{# {% endif %}#}


{% endfor %}


loop.index: 当前循环迭次的次数(从1开始)

loop.index0:当前循环迭代的次数(从0开始)

loop.revindex: 到循环结束需要迭的次数(从1开始)

loop.revindex0:到循环结束需要迭代的次数(从0开始)

loop.first 第一迭代,为True

loop.last 最后一次迭代,为True

loop.length  序列中的项目数

loop.cycle:在一串序列期间取值的辅助函数.

模板继承:

在模板中,可能会遇到以下情况:

  • 多个模板具有完全相同的顶部和底部内容
  • 多个模板中具有相同的模板代码内容,但是内容中部分值不一样
  • 多个模板中具有完全相同的 html 代码块内容

像遇到这种情况,可以使用 JinJa2 模板中的 继承 来进行实现

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/parent")

def parent():

  return render_template("base.html")

@app.route("/child")

def child():

  return render_template("child.html")

if __name__ == "__main__":

  app.run(debug=True)

base.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
{# 把要重写的父类的内容用{% block 名称x %} XXX {% endblock %}#}
{% block testA %}
<h2>父类模板<h2>
{% endblock %}
<h2>父类内容</h2>
<h2>父类底部</h2>

<body>

</body>
</html>

child.html内容:

{# 子类继承父类使用extends关键字 {% extends  '父类.html'  %}#}

{% extends "base.html'' %}

{# 重写父类中的部分内容#}

{# 不丢失父类原有的内容使用super()#}

{% block testA % }

{{super()}}

<h2>我是子类模板</h2>

{% endblock %}

怎样设置templates的html文件在使用render_template方法时自动弹出里面的html文件进行选择

选择Jinja2,apply之后点击ok即可

可以设置自己设置状态码及状态码解释

from flask import Flask

app = Flask(__name__)

@app.route("/")

def index():

  # 666代表状态码, 解释为状态码的解释信息

  return "hello world", "666 解释"

if __name__ == "__main__":

  app.run(debug=True)

原文地址:https://www.cnblogs.com/zhouzetian/p/9683550.html