flask学习1

 

总结

Flask Web 框架 轻量

websocket 全双工通讯 socket TCP 通讯

MongoDB 数据库 文件型数据库 {} 没有限制 和 约束

Mui + HTML5 Plus 调用移动操作系统的封装 IOS Android 

人工智能技术应用 BaiduAI
ASR 语音识别 声音转换成文字
TTS 语音合成 文字转换成声音
NLP 自然语言处理 你的名字叫什么 你的名字是什么 文本相似度
paddle paddle 百度
Ai studio

智能玩具 



Flask 
1.框架对比
Django                Flask
Admin - Model        原生无
Model                原生无
Form                原生无
Session                有 - 颠覆认知操作

教科书式框架        以简单为基准 开发 一切从简 能省则省

Django的优势:
    组件全,功能全,教科书
    
Django的劣势:
    占用资源,创建复杂度较高


Flask的优势:
    轻,快
    
Flask的劣势:
    先天不足,第三方组件稳定性较差


2.入门Flask 
pip3 install Flask
**Ps:不要使用工具中的插件创建Flask项目

三行代码启动 Flask 项目


3.Flask 中的 Response 
1.HTTPResponse("hello")     "" str
2.render 响应模板            render_template("html") str
3.redirect("/")                redirect("/")    str
以上是Web框架的 Response 三剑客
4.send_file()     instance     返回文件内容,自动识别文件类型,Content-type中添加文件类型,Content-type:文件类型
** 浏览器特性 可识别的Content-type 自动渲染 不可识别的Content-type 会自动下载

5.jsonify() str # 返回标准格式的JSON字符串 先序列化JSON的字典,Content-type中加入 Application/json
** Flask 1.1.1 版本中 可以直接返回字典格式,无需jsonify


4.Flask 中的 请求 Request
request.method 获取请求方式 
request.form 获取FormData中的数据 也就是所谓的Form标签 to_dict()
request.args 获取URL中的数据 to_dict()

request.json      请求中 Content-Type:application/json 请求体中的数据 被序列化到 request.json 中 以字典的形式存放
request.data    请求中 Content-Type 中不包含 Form 或 FormData 保留请求体中的原始数据 b""
request.files     获取Form中的文件

request.path    请求路径 路由地址
request.url        访问请求的完整路径包括 url参数
request.host    主机位 127.0.0.1:5000 
request.cookies 字典获取浏览器请求时带上的Cookie

** request.values 获取 url 和 FormData 中的数据 敏感地带

5.Jinja2 ---- template语言
{{ }} 引用 或 执行
{% %} 逻辑引用
View Code

Flask 入门

1.框架对比 Django Admin 组件- 基于Model实现的,Model,Form。教科书式框架

Flask 无Admin 原生无 Model 原生无 Form Session 有 - 颠覆认知操作。flask虽然原生没有,但是第三方组件特别多。只要有个人写个扩展功能出来,直接放到flask中,flask就能用了。第三方组件多,强大。如果包括第三方组件,那么flask比Django功能还要多。缺点:flask自己是不支持那么多组件的,官方认可,但不代表是他们开发的,所以当flask版本升级了,有可能使得第三方组件用不了了。flask宗旨:以简单为基准 开发 一切从简 能省则省。这个session没有摒弃,因为它占有资源非常少

Django的优势:  组件全,功能全,教科书   Django的劣势:  占用资源,创建(开发)复杂度较高

Flask的优势:  轻,快   Flask的劣势:  先天不足,第三方组件稳定性较差

2.入门Flask

pip3 install Flask **Ps:不要使用工具中的插件创建Flask项目

三行代码启动 Flask 项目

flask学习1_第1张图片

不要勾选继承全局包,不然会复制一份包过来,会很慢,直接创建新的。

安装flask组件

flask学习1_第2张图片

 

 flask学习1_第3张图片

卸载之后换个版本

flask学习1_第4张图片

Flask框架源码,Jinja2模板语言,Django里template是基于Jinja2实现的。MarkupSafe是后端给前端传递字符串,将字符串转为标签来展示在浏览器中使用的。render底层就是基于它。Werkzeug ① 工具 ② (动物的某一)器官 ③ 工具(指人、机构等) .Werkzeug 相当于Django的uwsgi,承载服务用的,类似于tomcat,jboss等web服务,应用程序网关接口,它和uwsgi的底层是一样的,都是wsgi。这些是flask的主要依赖包

flask学习1_第5张图片

创建一个flask项目。启动项目。

from flask import Flask

app=Flask(__name__)

app.run()

flask学习1_第6张图片

成功访问:

在去查看访问情况,可以看到后台获取/,但是资源没有找到,这是应用层抛出的错误。如果服务没起就访问,抛出的就不是404了,比如超时等之类的错误

flask学习1_第7张图片

flask实现hello world

如果@app.route()每加路由,那么报错:TypeError: route() missing 1 required positional argument: 'rule'

from flask import Flask

app=Flask(__name__)

@app.route("/")
def home():
  return "hello world I am mcw"

app.run()

/是路由地址,定义视图函数,直接返回字符串。可以在浏览器上显示出返回的字符串。下面我们就可以用这三行代码实现flask所有的功能。

访问情况:

如果没有返回内容,那么会报错500服务器异常:

Internal Server Error

The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.

flask学习1_第8张图片

 

 flask学习1_第9张图片

我们的视图函数没有返回值,那么就是默认返回的None,即使我们给函数后面添加一个return None,结果没有什么变化,这是因为flask返回值是有限制

3.Flask 中的 Response

访问如下服务

flask学习1_第10张图片

可以看到返回的是字符串

flask学习1_第11张图片

响应头中的内容类型是文本。这个内容类型决定了浏览器使用的渲染方式。

flask学习1_第12张图片

而这里表示这是个文本内容,要用html的格式显示出来。这些标签不是我们返回的,我们只是返回下面显示的字符串。这是浏览器读取到了内容类型,帮我们将字符串加了这些标签。

flask学习1_第13张图片

1.

HTTPResponse("hello") "" str

2.render_template

render 响应模板 render_template("html") str

Django中是template。这里因为创建多个模板文件,我们在程序当前目录创建一个templates目录。

并且导入render_template,让函数返回render_template("模板文件名字"),这样当客户端访问这个路由的时候,就能访问到这个模板渲染出来的信息了。

from flask import Flask,render_template

app=Flask(__name__)

@app.route("/index")
def home():
  return render_template("index.html")

app.run()

名字写错了报错:

flask学习1_第14张图片

前端文件如下:




 
  Title


我是mcw

flask学习1_第15张图片

访问情况如下,响应头内容类型中显示内容类型是文本:

flask学习1_第16张图片

我们可以看到模板文件深黄色的,这是编辑器层面也就是pycharm给我们添加的可能出现的错误的提醒。这都是编辑器查找不到所出现的错误。这是pycharm并不知道我们的模板目录,我们可以去掉这个颜色。我们可以将这个目录标记为模板目录

flask学习1_第17张图片

是否选择一个支持的语言,

flask学习1_第18张图片

这里有Django的template语言。我们要选的是Jinja2语言

flask学习1_第19张图片

然后可以看到,模板语言的深黄色标记已经消失

flask学习1_第20张图片

3.redirect("/")

redirect("/") str 以上是Web框架的 Response 三剑客

from flask import Flask,render_template,redirect

app=Flask(__name__)

@app.route("/index")
def home():
  return render_template("index.html")
@app.route("/login")
def login():
  return redirect("/index")

app.run()

我访问login的时候,跳转到index了

flask学习1_第21张图片

查看login详情,可以看到响应头中添加了location,重定向的地址。响应头中包含location,就会跳转。而redirect所做的事情就是在响应头中添加了location

flask学习1_第22张图片

4.send_file()

from flask import Flask,render_template,redirect,send_file

app=Flask(__name__)

@app.route("/index")
def home():
    return  render_template("index.html")
@app.route("/login")
def login():
    return  redirect("/index")
@app.route("/get_file")
def get_file():
    return  send_file("git-cmd.exe")

app.run()
View Code

instance 返回文件内容,自动识别文件类型,Content-type中添加文件类型,Content-type:文件类型 ** 浏览器特性 可识别的Content-type 自动渲染 不可识别的Content-type 会自动下载

我们导入send_file,

from flask import Flask,render_template,redirect,send_file

app=Flask(__name__)

@app.route("/index")
def home():
  return render_template("index.html")
@app.route("/login")
def login():
  return redirect("/index")
@app.route("/get_file")
def get_file():
  return send_file("app.py")

app.run()

flask学习1_第23张图片

访问这个url,可以看到,把这个文件保留原格式的显示在浏览器上了

flask学习1_第24张图片

 

 

 我们可以看到响应头的类型中是文本格式,

flask学习1_第25张图片

 

 

 它给我们添加了html标签显示。text/plain就是要保留当前文件格式的

flask学习1_第26张图片

 那么能不能返回二进制文件呢?这里有张照片

flask学习1_第27张图片

 我们返回这个照片

flask学习1_第28张图片

 然后访问,可以看到可以访问到这个照片了。这是flask给响应头设置了内容格式。返回文件内容,自动识别文件类型,Content-type中添加文件类型

flask学习1_第29张图片

 

 

 当放的是个mp3的时侯

flask学习1_第30张图片

 

 

 浏览器上访问,可以发现黑底,图标,然后播放。可以点击暂停。这是流媒体,它不会一次就加载完,分很多次给你加载

flask学习1_第31张图片

 

 详情里可以看它的内容类型和内容长度。电影也是这样,分很多次加载。audio是音频文件,mp格式的,mpeg就是保护mp3,4等一系列mp开头的。

flask学习1_第32张图片

 

 查看渲染的标签是啥,这里是video,实际上我们的是audio,那么为什么用video渲染呢

flask学习1_第33张图片

 

 下面我们发送一个mp4的视频

flask学习1_第34张图片

 

 然后访问查看,这里显示的就是video了

flask学习1_第35张图片

 

 查看渲染的还是video,这是因为无论是视频还是音频,无法区分的太多,浏览器就拿出错几率最小的来渲染,用video 视频音频都可以渲染

flask学习1_第36张图片

 

 假如我们修改为发送一个Windows可执行文件,

flask学习1_第37张图片

 

 那么浏览器不能认识,就会让你下载。x可执行的 ,ms 微软,下载

flask学习1_第38张图片

 

 这体现一个浏览器特性

** 浏览器特性 可识别的Content-type 自动渲染 不可识别的Content-type 会自动下载

 

5.jsonify() str

# 返回标准格式的JSON字符串 先序列化JSON的字典,Content-type中加入 Application/json
** Flask 1.1.1 版本中 可以直接返回字典格式,无需jsonify

写个函数,导入jsonify。快捷导入模块,ALT+enter键显示出导入啥模块,查看正确就按enter键确认导入,就能快速导入模块

flask学习1_第39张图片

 

 然后它默认在结尾加上了

 

 如下写

flask学习1_第40张图片

 

 访问情况如下:可以看到响应头内容类型是json,并且有数据长度

flask学习1_第41张图片

 

如果我们返回的是个字典

flask学习1_第42张图片

 

 那么它会将字典返回,并且在浏览器上显示出来。如果没有序列化正常来说是不能返回,但是flask 1.1.1是可以返回字典的,返回的也是application/json格式,实际上它也是使用的jsonify实现的。

flask学习1_第43张图片

 

 如下可以看出来可以直接return的,其中包含字典,实际上它还是会转成字符串,这是1.1.1版本

flask学习1_第44张图片

jsonify() str # 返回标准格式的JSON字符串 先序列化JSON的字典,Content-type中加入 Application/json
** Flask 1.1.1 版本中 可以直接返回字典格式,无需jsonify

 

 一般写api的时候要用到

4.Flask 中的 请求 Request

from flask import Flask,request

app=Flask(__name__)

@app.route("/login")
def login():
    #优先判断 请求方式
    #如果是GET请求,返回登录页
    #如果是POST请求  获取用户密码 校验

if __name__ == '__main__':
    app.run()
View Code

写一个登陆函数写上导入时不执行run,flask中request是一个公共变量,导入这个变量。

flask学习1_第45张图片

我们可以找到这个变量,这是个公共变量,小写,常量一般是大写。公共变量也就是request是可以被多个线程修改的。request中有个管理机制叫请求上下文管理 

flask学习1_第46张图片

request.method 获取请求方式

 

 

 flask学习1_第47张图片

 

 

 现在函数如下:如果请求方式是get,那么返回登录也面

from flask import Flask,request,render_template

app=Flask(__name__)

@app.route("/login")
def login():
#优先判断 请求方式
if request.method == "GET":
#如果是GET请求,返回登录页
return render_template("login.html")
#如果是POST请求 获取用户密码 校验

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

登录页面如下:添加了登录的form表单


"en">

    "UTF-8">
    魔降风云变


"" method="post"> "text" name="username"> "submit" value="登录">

访问情况如下:

 

 

 我输入内容点击登录如下,显示方式不被允许。405错误码就是请求方式不被允许,也就是当前的视图函数不允许post提交

flask学习1_第48张图片

 

 

 后台报错:127.0.0.1 - - [03/Feb/2022 11:12:14] "POST /login HTTP/1.1" 405 -

 

我们在路由上面添加参数methods,写上支持的请求方式包括get和post,这里写上之后,不是追加,而是覆盖 ,所以要添加上get,这里是可迭代对象列表或者元组,然后打印一下form

flask学习1_第49张图片

 

 

 然后我们再访问提交

成功打印出来前端提交过来的数据了

 

 

提交过来数据是个字典,我们可以让它直接转化成字典,可以如下to_dict()操作

 

 

 

 flask学习1_第50张图片

 

 

 也可以用如下方式直接取字典中的值

flask学习1_第51张图片

 

 

 如果用中括号取索引,当索引未取到时会报错,所以尽量用get取索引

flask学习1_第52张图片

 

 

 flask学习1_第53张图片 

产生 HTTP 400 错误的原因有:

  • 1、前端提交数据的字段名称或者是字段类型和后台的实体类不一致,导致无法封装;
  • 2、前端提交的到后台的数据应该是 json 字符串类型,而前端没有将对象转化为字符串类型;
@app.route("/login",methods=["GET","POST"])
def login():
    #优先判断 请求方式
    #如果是GET请求,返回登录页
    if request.method == "GET":
        return render_template("login.html")
    #如果是POST请求  获取用户密码 校验
    else:
        print("to_dict",request.form.to_dict())
        if request.form.get("username") == "mcw":
            return "mcw login suceess"
    return "200 OK"
View Code

flask学习1_第54张图片

 

 

 上面就可以对获取到的用户做校验,校验通过就让它成功登陆

 

 

 

 

 

request中还有别的请求方式。在传递url的时候,我们可以使用url进行传参,那么我们如果获取url中的传参呢,args。如下,我们在url中拼接id=1的参数进行访问

 

后端程序获取url传参,这个传参也可以使用转化到字典的方法。url中除了可以传递参数,还可以传递文件,使用的是base64。

 

 flask学习1_第55张图片

 

 

 ** request.values 获取 url 和 FormData 中的数据 这个里面有个坑,尽量不用,就是url中的参数会覆盖掉FormData中的数据

 当我们访问如下地址的时侯

 

 

 flask学习1_第56张图片

 

 

 可以看request中的打印信息:

flask学习1_第57张图片

 

 

 request.path 请求路径 路由地址 /login
request.url 访问请求的完整路径包括 url参数
request.host 主机位 127.0.0.1:5000   ip+端口
request.cookies 字典获取浏览器请求时带上的Cookie

 

下面看request.files,前端添加数据类型,添加file类型的标签,标签名称为my_file


"en">

    "UTF-8">
    魔降风云变


"" method="post"> "text" name="username" formenctype="multipart/form-data"> "file" name="my_file"> "submit" value="登录">
View Code

flask学习1_第58张图片

 

 

 程序打印一下,files

flask学习1_第59张图片

 

 

 访问情况如下:

 

 

 我们上传个文件,点击登录

 

 

 显示没有登录成功

 

 

 打印出来是这样的

flask学习1_第60张图片

 

 

 刚刚位置写错了,重新来:

flask学习1_第61张图片

 

 

 修改正确之后,就能获取到上传文件的信息了,有一个文件存储对象,是我们上传的图片

flask学习1_第62张图片

 

 

 下面我们修改重启上传点击登录,可以看到获取到上传的文件存储对象了

flask学习1_第63张图片

 

 

 下面我们操作这个文件存储对象,将这个文件保存到服务端

 上传

 

 

 查看结果,可以看到已经使用上传文件的文件名为名称,将文件保存到服务端了了。

flask学习1_第64张图片

 

 

 一般上传上来我们给它重新命令,比如上传上来一个头像,我们这里创建一个头像目录叫avatar。那么我们首先要找到这个目录,然后我们将文件名和目录拼接在一起,最后是save

这样就成功上传了文件

 

 

 flask学习1_第65张图片

 

 不只是响应当中有content type ,请求当中也有内容类型。如下,enctype

 flask学习1_第66张图片

 

 request.json 请求中 Content-Type:application/json 请求体中的数据 被序列化到 request.json 中 以字典的形式存放
request.data 请求中 Content-Type 中不包含 Form 或 FormData 保留请求体中的原始数据 b"" 即Byte。请求的本质上是一个socket传输,传输不能直接传字符串,得用bytes,这里就保留流的原始信息,data一般用的少,比如前端写错了,比如类型不识别就保存原始数据到data里面

 

总结:

request.form 获取FormData中的数据 也就是所谓的Form标签 to_dict()
request.args 获取URL中的数据 to_dict()

request.json 请求中 Content-Type:application/json 请求体中的数据 被序列化到 request.json 中 以字典的形式存放
request.data 请求中 Content-Type 中不包含 Form 或 FormData 保留请求体中的原始数据 b""
request.files 获取Form中的文件

request.path 请求路径 路由地址
request.url 访问请求的完整路径包括 url参数
request.host 主机位 127.0.0.1:5000
request.cookies 字典获取浏览器请求时带上的Cookie

** request.values 获取 url 和 FormData 中的数据 敏感地带

5.Jinja2

---- template语言
{{ }} 引用 或 执行
{% %} 逻辑引用

1、如下,三个数据结构的数据。初始的程序。

2、这里app.config["DEBUG"]=True和app.debug=True都是为了实现修改程序之后,无需重启程序,自动生效。当客户端访问过来就访问的是最新的程序

3、app.run("0.0.0.0",9527) 指定任意地址都能访问,监听端口为9527,即服务端口

单个字典

STUDENT = {'name': 'mcw01', 'age': 38, 'gender': '中'},

STUDENT_LIST = [
{'name': 'mcw01', 'age': 38, 'gender': '中'},
{'name': 'mcw02', 'age': 73, 'gender': '男'},
{'name': 'mcw03', 'age': 84, 'gender': '女'}
]

STUDENT_DICT = {
1: {'name': 'mcw01', 'age': 38, 'gender': '中'},
2: {'name': 'mcw02', 'age': 73, 'gender': '男'},
3: {'name': 'mcw03', 'age': 84, 'gender': '女'},
}

from flask import Flask

app=Flask(__name__)
app.config["DEBUG"]=True
app.debug=True

if __name__ == '__main__':
app.run("0.0.0.0",9527)

由于起名字问题,用jinja2了,结果执行这个文件时把源码中所有从jinja2导入的变成从自己新建文件导入,导致很多导入出错问题。我把新建文件改了名字为模板学习,所有从jinja2导入的变成草丛模板学习导入的了,虽然把文件名改回来了,但是还有问题的

flask学习1_第67张图片

 

 

 后来把源码改回去了,果然是因为本地起名冲突,导致从本地导入,结果出现问题了

flask学习1_第68张图片

 

 

 下面还有很多行出问题,修改一行我就继续让它出现下一个,再修改,后面就好了

flask学习1_第69张图片

 

 

 如下,传递一个字典进模板,这里用的是关键字传参

STUDENT = {'name': 'mcw01', 'age': 38, 'gender': ''},

STUDENT_LIST = [
    {'name': 'mcw01', 'age': 38, 'gender': ''},
    {'name': 'mcw02', 'age': 73, 'gender': ''},
    {'name': 'mcw03', 'age': 84, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': 'mcw01', 'age': 38, 'gender': ''},
    2: {'name': 'mcw02', 'age': 73, 'gender': ''},
    3: {'name': 'mcw03', 'age': 84, 'gender': ''},
}

from flask import Flask,render_template

app=Flask(__name__)
# app.config["DEBUG"]=True
app.debug=True
@app.route("/")
def home():
    return render_template("stu.html",stu=STUDENT)

if __name__ == '__main__':
    app.run("0.0.0.0",9527)
视图函数

"en">

    "UTF-8">
    魔降风云变


{{ stu }}

前端

 

 

 flask学习1_第70张图片

 

 

 

 然后在模板里引用

 

 

 当浏览器访问的时候,显示的是字典被包在元组当中,为啥有个元组呢,跟预期的不符合,是因为传递的字典多了个逗号,将逗号去掉就好了,前端展示的是字典才是正常的

 

 

 flask学习1_第71张图片

 

 

 修改如下:取值可以点取,中括号取,或者get取stu中被传递过来的字典中的数据

flask学习1_第72张图片

 flask学习1_第73张图片

 

 

 flask学习1_第74张图片

 

 

 以上就是单个字典的使用

列表中每个元素都是字典

下面就是列表中多个字典的使用,需要使用for循环

使用for循环

flask学习1_第75张图片

 

 

 将列表以关键字参数传递进去

flask学习1_第76张图片

 

 

 

 我不想要中,当不是男不是女的时候想要它是女

这样就要添加判断语句,当这个值不是男并且不是女的时候,显示女,否则显示当前值

flask学习1_第77张图片

 

 

 这样就正常显示性别了

flask学习1_第78张图片

 

 

 字典中每个键值对的值都是字典1

将它传进去

flask学习1_第79张图片

 

 循环每个字典的键,字典加键获取内层字典,然后使用内层字典的数据

flask学习1_第80张图片

 

 结果:

flask学习1_第81张图片

 字典中每个键值对的值都是字典2

这次不是循环字典的键,而是循环字典的items,items后面记得加括号。也可只拿键或者值,keys(),values()

flask学习1_第82张图片

 

 结果:

flask学习1_第83张图片

 

 传递自定义函数到模板中,以及将自定义函数作为所有模板共用的函数

自定义一个函数,定义一个视图函数,在视图函数中将函数传递到模板文件中

flask学习1_第84张图片

 

 在模板中使用这个函数,

flask学习1_第85张图片

 

 那么函数的执行结果会渲染在这个模板中,访问结果如下

flask学习1_第86张图片

 

 下面将这个ab函数设置为模板共用的

只需将函数前面加个装饰器,就使它变成全局的模板了,并且不需要传递ab这个函数,在模板中就能调用这个函数。否则,如果有100个视图函数,那么100个视图函数都要传递一次ab函数

flask学习1_第87张图片

 

 访问结果:

 

 flask学习1_第88张图片

 

 宏指令(几乎不用)

前端模板文件中生成宏指令,然后在模板中传参使用,如下栗子:

模板文件中生成宏指令,后面再传参调用,就生成想要的标签,这个直接传递函数应该也可以,更好吧。

flask学习1_第89张图片

 

 访问可以看到生成的标签

flask学习1_第90张图片

 

 后端生成html传递到模板文件中

flask学习1_第91张图片

 

 前端调用一下

flask学习1_第92张图片

 

 可以看到它是字符串,这时需要将它转换成标签显示

flask学习1_第93张图片

 

前端使用safe就可以实现,如果在不能改动前端的基础上实现将传递的字符串过去,作为标签显示出来,那么...

 flask学习1_第94张图片

 

 flask学习1_第95张图片

 

 不修改前端添加safe的话,那么给传递的标签字符串改为markup字符串,即将字符串用Markup包起来

flask学习1_第96张图片

flask学习1_第97张图片

 

 后端生成前端html组件的函数

生成的组件,我们可以变成全局,然后每个模板中调用函数,或者是视图函数中将这个函数传递进模板使用

 

 flask学习1_第98张图片

STUDENT = {'name': 'mcw01', 'age': 38, 'gender': ''}

STUDENT_LIST = [
    {'name': 'mcw01', 'age': 38, 'gender': ''},
    {'name': 'mcw02', 'age': 73, 'gender': ''},
    {'name': 'mcw03', 'age': 84, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': 'mcw01', 'age': 38, 'gender': ''},
    2: {'name': 'mcw02', 'age': 73, 'gender': ''},
    3: {'name': 'mcw03', 'age': 84, 'gender': ''},
}

from flask import Flask,render_template,Markup,session,sessions

app=Flask(__name__)
# app.config["DEBUG"]=True
app.debug=True
@app.route("/")
def home():
    print(STUDENT)
    return render_template("stu.html",stu=STUDENT,stu_l=STUDENT_LIST,stu_d=STUDENT_DICT)
@app.template_global()
def ab(a,b):
    return a+b

@app.template_global()
def my_input(na,ty):
    s=f""
    return Markup(s)

@app.route("/a")
def homea():
    inp=Markup("")
    return render_template("my_a.html",btn=inp)

if __name__ == '__main__':
    app.run("0.0.0.0",9527)
视图函数

"en">

    "UTF-8">
    魔降风云变


{{ ab(4,2) }}
{{ stu }}
列表中每个值都是字典: "1" cellspacing="0"> {% for student in stu_l %} {% endfor %}
name age gender
{{ student.name }} {{ student["age"] }} {% if student.get("gender") !="" and student.get("gender") !="" %} 女 {% else %} {{ student.get("gender") }} {% endif %}
字典中的每个值都是字典: "1" cellspacing="0"> {# {% for skey in stu_d %}#} {# #} {# #} {# #} {# #} {# #} {# {% endfor %}#} {% for skey,svlue in stu_d.items() %} {% endfor %}
name age gender
{{ stu_d.get(skey).name }}{{ stu_d.get(skey)["age"] }}#} {# {% if stu_d.get(skey).get("gender") !="" and stu_d.get(skey).get("gender") !="" %}#} {# 女#} {# {% else %}#} {# {{ stu_d.get(skey).get("gender") }}#} {# {% endif %}#} {#
{{ skey }} {{ svlue.name }} {{ svlue["age"] }} {% if svlue.get("gender") !="" and svlue.get("gender") !="" %} 女 {% else %} {{ svlue.get("gender") }} {% endif %}
前端文件

Flask中的session

简单介绍

session和request在这里,除了session和request不一样,其它都是一样的。

这里的session基于请求上下文机制

flask学习1_第99张图片

 

 

 当导入session的时候,可以看到有个sessions,这是个文件,session都是基于这个文件来的

flask学习1_第100张图片

 

 

 flask学习1_第101张图片

 

 

 flask学习1_第102张图片

 

 使用简单栗子

 先写一个登录函数

@app.route("/login",methods=["GET","POST"])
def login():
    if request.method == "GET":
        return render_template("login.html")
    else:
        user_info=request.form.to_dict()
        print(user_info)
        return "login OK!"
登录函数

flask学习1_第103张图片

 

 

 可以正常访问

flask学习1_第104张图片

 

 

 flask学习1_第105张图片

 

 

 现在我们需要的不是打印userinfo,而是获取到用户名然后存进session中

flask学习1_第106张图片

 

 

 获取到用户名并保存进session中,但是报错了

RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret.

flask学习1_第107张图片

 

 

 为什么后端也能看到报错信息呢,在这里是因为debug现在设置的true,所以会把后端报错映射到前端展示出来

flask学习1_第108张图片

 

 

 翻译一下。我们的flask应用承载在workzauk上,workzauk是个wsgi,wsgi收到请求之后把请求序列化了,然后扔给我们的应用,我们的应用就是flask实例。也就是我们的app就是我们的application。

 

 

 

 那么我们就在应用上生成一个secret_key。这里随便写的

app.secret_key="$@IIO#JD)@(&@^#$NFNAJOOK;k%@#)FJO(@*$&#*ccsia86"

 

 

 

 我们再次请求试试

 

 

 

 

 

 在session中获取到值,也就是我们成功的把前端提交的数据保存到session中了

flask学习1_第109张图片

 

 session保存机制以及使用

 Django的session是存到数据库里了,那么flask的session是存到哪里了呢。session的生命周期,这里默认是31天。如果把session中获取的数据放到get方式下,当get请求时,也是每次请求都会打印出这个session的内容。即使把pycharm关掉重新打开,然后访问还是可以打印出来。

 我们可以看到session保存到浏览器上面了。在应用的cookies下可以看到

flask学习1_第110张图片

 

 

 当我们把它删除掉之后,

flask学习1_第111张图片

 

 

 发送一个get请求,可以发现获取的值是None了,之前获取的是mcw,正常的数据。当我们重新输入名字,点击登录,就会重新产生session又能重新获取到了。

flask学习1_第112张图片

 

 

 现在浏览器上重新登录后,有了新的session了

flask学习1_第113张图片

 

 

 我在secret_key开头加个1。

flask学习1_第114张图片

 

 

 然后再次访问,可以看到获取到的是None

 flask学习1_第115张图片

 

 

 当把新增的1去掉后,重新访问

 

 

 发现又有了。这是因为密钥被修改了,原来加密的用被修改过的密钥配不上,

flask学习1_第116张图片

 

 session登录状态,单个函数使用

 如下,现在/a的页面如下:

 

 

 

 /login页面如下:

 

 

 我需要实现当访问/a页面时,如果登录了,就正常访问;如果没有登录,那么返回登录页进行登录

STUDENT = {'name': 'mcw01', 'age': 38, 'gender': ''}

STUDENT_LIST = [
    {'name': 'mcw01', 'age': 38, 'gender': ''},
    {'name': 'mcw02', 'age': 73, 'gender': ''},
    {'name': 'mcw03', 'age': 84, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': 'mcw01', 'age': 38, 'gender': ''},
    2: {'name': 'mcw02', 'age': 73, 'gender': ''},
    3: {'name': 'mcw03', 'age': 84, 'gender': ''},
}

from flask import Flask, render_template, Markup, session, sessions, request, redirect

app=Flask(__name__)
# app.config["DEBUG"]=True
app.debug=True
app.secret_key="$@IIO#JD)@(&@^#$NFNAJOOK;k%@#)FJO(@*$&#*ccsia86"
@app.route("/")
def home():
    print(STUDENT)
    return render_template("stu.html",stu=STUDENT,stu_l=STUDENT_LIST,stu_d=STUDENT_DICT)
@app.template_global()
def ab(a,b):
    return a+b
@app.template_global()
def my_input(na,ty):
    s=f""
    return Markup(s)
@app.route("/a")
def homea():
    #校验用户登录状态?
    #校验session中有没有user Key
    if session.get("user"):
        inp=Markup("")
        return render_template("my_a.html",btn=inp)
    #校验失败,跳转login
    else:
        return redirect("/login")
@app.route("/login",methods=["GET","POST"])
def login():
    if request.method == "GET":
        print(session.get("user"))
        return render_template("login.html")
    else:
        user_info=request.form.to_dict()
        session["user"]=user_info.get("username")
        print(session.get("user"))
        return "login OK!"

if __name__ == '__main__':
    app.run("0.0.0.0",9527)
View Code

flask学习1_第117张图片

 

 现在能正常访问,我把session删掉重新访问

flask学习1_第118张图片

 

 删除session之后,访问/a就302跳转到/login了,符合预期

flask学习1_第119张图片

 session多个页面使用,多层装饰器使用

 虽然/a实现了登录才能访问,但是/首页却是没有实现,如果每个视图函数都写一遍,显然是不可能。

flask学习1_第120张图片

 

 既然不能每个视图函数都写,那么就用装饰器实现,这里先写一个装饰器

flask学习1_第121张图片

 

多层装饰器的执行顺序是自下而上执行的。我们需要看这个最终装饰的函数是谁,再去做装饰器的叠加。war装饰之后返回的是inner,inner就是home,home需要被route装饰。route在war上面,那么war返回的home就被route装饰,如果没有route装饰,那么肯定就无法响应数据。比如war放到route上了,那么route先给响应了,还没有到war装饰呢。所以route放到最外层,它要做响应数据。而这里的war我们是为了做session校验用的。

 flask学习1_第122张图片

 

 如下,就完成了使用装饰器进行session校验。在每个视图函数前加上这个装饰器

flask学习1_第123张图片

 

 现在我们再次访问/,发现302跳转到登录页了

flask学习1_第124张图片

 

 当我们登录有了session之后

flask学习1_第125张图片

 

 再次访问/,直接访问成功

flask学习1_第126张图片

程序汇总

STUDENT = {'name': 'mcw01', 'age': 38, 'gender': ''}

STUDENT_LIST = [
    {'name': 'mcw01', 'age': 38, 'gender': ''},
    {'name': 'mcw02', 'age': 73, 'gender': ''},
    {'name': 'mcw03', 'age': 84, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': 'mcw01', 'age': 38, 'gender': ''},
    2: {'name': 'mcw02', 'age': 73, 'gender': ''},
    3: {'name': 'mcw03', 'age': 84, 'gender': ''},
}

from flask import Flask, render_template, Markup, session, sessions, request, redirect

app=Flask(__name__)
# app.config["DEBUG"]=True
app.debug=True
app.secret_key="$@IIO#JD)@(&@^#$NFNAJOOK;k%@#)FJO(@*$&#*ccsia86"

def war(func):
    def inner(*args,**kwargs):
        #校验session
        if session.get("user"):
            ret=func(*args,**kwargs) #func=home
            return ret
        else:
            return redirect("/login")
    return inner

@app.route("/")
@war
def home():
    print(STUDENT)
    return render_template("stu.html",stu=STUDENT,stu_l=STUDENT_LIST,stu_d=STUDENT_DICT)
@app.template_global()
def ab(a,b):
    return a+b
@app.template_global()
def my_input(na,ty):
    s=f""
    return Markup(s)
@app.route("/a")
def homea():
    #校验用户登录状态?
    #校验session中有没有user Key
    if session.get("user"):
        inp=Markup("")
        return render_template("my_a.html",btn=inp)
    #校验失败,跳转login
    else:
        return redirect("/login")
@app.route("/login",methods=["GET","POST"])
def login():
    if request.method == "GET":
        print(session.get("user"))
        return render_template("login.html")
    else:
        user_info=request.form.to_dict()
        session["user"]=user_info.get("username")
        print(session.get("user"))
        return "login OK!"

if __name__ == '__main__':
    app.run("0.0.0.0",9527)
视图函数

"en">

    "UTF-8">
    Title


我是mcw

index.html

"en">

    "UTF-8">
    魔降风云变


"" method="post" enctype="multipart/form-data"> "text" name="username" > "file" name="my_file"> "submit" value="登录">
login.html

"en">

    "UTF-8">
    Title


{{ ab(1,2) }}
    {% macro my_input(na,ty) %}
        "{{ ty }}" name="{{ na }}">
    {% endmacro %}
     {{ my_input("username","password") }}
    {{ btn }}

my_a.html

"en">

    "UTF-8">
    魔降风云变


{{ ab(4,2) }}
{{ stu }}
列表中每个值都是字典: "1" cellspacing="0"> {% for student in stu_l %} {% endfor %}
name age gender
{{ student.name }} {{ student["age"] }} {% if student.get("gender") !="" and student.get("gender") !="" %} 女 {% else %} {{ student.get("gender") }} {% endif %}
字典中的每个值都是字典: "1" cellspacing="0"> {# {% for skey in stu_d %}#} {# #} {# #} {# #} {# #} {# #} {# {% endfor %}#} {% for skey,svlue in stu_d.items() %} {% endfor %}
name age gender
{{ stu_d.get(skey).name }}{{ stu_d.get(skey)["age"] }}#} {# {% if stu_d.get(skey).get("gender") !="" and stu_d.get(skey).get("gender") !="" %}#} {# 女#} {# {% else %}#} {# {{ stu_d.get(skey).get("gender") }}#} {# {% endif %}#} {#
{{ skey }} {{ svlue.name }} {{ svlue["age"] }} {% if svlue.get("gender") !="" and svlue.get("gender") !="" %} 女 {% else %} {{ svlue.get("gender") }} {% endif %}
stu.html
import os

from flask import Flask,request,render_template

app=Flask(__name__)

@app.route("/login",methods=["GET","POST"])
def login():
    #优先判断 请求方式
    #如果是GET请求,返回登录页
    if request.method == "GET":
        return render_template("login.html")
    #如果是POST请求  获取用户密码 校验
    else:
        my_file=request.files.get("my_file")
        filename=my_file.filename #获取原始文件名
        file_path=os.path.join("avatar",filename)
        my_file.save(file_path)
        if request.form.get("username") == "mcw":
            return "mcw login suceess"
    return "login not OK"
if __name__ == '__main__':
    app.run()
app.py

 

你可能感兴趣的:(flask学习1)