一:安装和初始
- 1.Flask 安装 + 启动
- from flask import Flask
- app = Flask(__name__) # 实例化flask对象 # __name__ 多app应用,分区实例在哪个文件中
- app.run()
-
- 高级启动:
- from flask import Flask
- app = Flask(__name__)
-
- @app.route("/") # app中的rotue装饰器
- def home(): # 视图函数
- return "Hello World!"
-
- app.run()
二: Render, Redirect HttpResponse
- 2.Flask Response
- 1.HttpResponse("HelloWorld") "HelloWorld" 返回字符串
- from flask import render_template 默认存放路径 templates
- 2.render("模板路径") render_template 返回模板
- from flask import redirect 重定向
- 3.redirect("/")
-
- Flask 中的返回特殊封装 2个
- 1.jsonify 转换标准JSON格式
- 响应头中加入 Content-type:application/json
- 在Flask 1.1.1 版本中 加入了 直接返回字典 可以不再使用jsonify了
-
- 2.send_file 发送文件
- 打开并返回文件内容,
- 自动识别文件类型,
- 响应头中加入Content-type:文件类型 # Content-Type: audio/mpeg
- ps:当浏览器无法识别Content-type时,会下载文件
-
- # 大的视频文件是 分段式请求
- # 打开并返回文件内容,自动识别文件类型,content-type:文件类型
-
- # Ps:
- # 浏览器无法识别content-type时,都以下载返回。 识别的话,直接打开
-
- from flask import Flask, render_template, redirect, jsonify, send_file
-
- # Alt + 回车 快速的导入模块
-
-
- app = Flask(__name__) # 实例化flask对象 # __name__ 多app应用,分区实例在哪个文件中
-
- app.config["DEBUG"] = True # 能够随时更改自动重启,不加的话每次更改代码需要手动重启
-
-
- @app.route("/") # app中的rotue装饰器
- def home(): # 视图函数
- # return 1
- # TypeError: The view function did not return a valid response.
- # The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a int.
-
- return "home"
-
-
- @app.route("/index")
- def index():
- return render_template("index.html")
-
-
- @app.route("/reback")
- def reback():
- return redirect('/index')
-
-
- @app.route("/json")
- def my_jsonify():
- # return jsonify({"a":1})
- return {"k": "v"}
-
-
- @app.route("/myfile")
- def my_file():
- # return send_file('1chushi.py')
- # return send_file('1.jpg')
- return send_file('ss.mp3')
-
- # 传文件
- # 不管video还是audio都是显示 Audio
-
- app.run()
三:Request
- 3.Flask Request
- 假登录
- 405 请求方式不被允许 - GET请求可以 POST请求 405 Method Not Allowed
- Form表单 - FormData
- f orm - 表单
-
- from flask import request 公共对象
-
- 1.request.form 获取FormData中的数据 - Form表单
- 2.request.args # 获取URL中的参数
- 3.request.files # 获取FormData中的文件数据
-
- print(request.url) # 获取访问路径
- print(request.method) # 获取请求方式
- print(request.path) # 路由地址 /login
- print(request.values) # Form 和 Args 中的数据
- # 综合获取 X
- print(request.args.get("id")) # 获取URL中的参数
- print(request.args["id"]) # 获取URL中的参数
- print(request.args.to_dict()) # 获取URL中的参数 转换成 字典
-
- print(request.environ) # 获取请求原始信息
- print(request.base_url) # 获取URL头,不包含参数
-
- print(request.json) # 毁三观 1 请求头中 Content-type:application/json 数据序列化 request.json
- print(request.data) # 毁三观 2 请求头中 Content-type 不包含 Form or data
-
- print(request.headers) # 请求头中的数据
3.1:request.py
- from flask import Flask, render_template, request
- import os
-
- app = Flask(__name__)
- app.config["DEBUG"] = True # 能够随时更改自动重启,不加的话每次更改代码需要手动重启
-
-
-
- @app.route("/login", methods=["POST", "GET"])
- def login():
- if request.method == "GET":
-
- print(request.url) # 获取访问路径
- # request.url: http://127.0.0.1:5000/login
- # request.url: http://127.0.0.1:5000/login?id=1
-
- print(request.method) # 获取请求方式
- # GET
- # GET
-
- print(request.path) # 路由地址 /login
- # /login
- # /login
-
- print(request.values) # 可以获取URL中的参数 也可以获取 FormData中的数据
- # 综合获取 ,可以获取url 和 formdata的数据
- # CombinedMultiDict([ImmutableMultiDict([]), ImmutableMultiDict([])])
- # CombinedMultiDict([ImmutableMultiDict([('id', '1')]), ImmutableMultiDict([])])
-
-
- print(request.args)
- # ImmutableMultiDict([('id', '1')])
-
-
- print(request.args.to_dict()) # 获取URL中的参数 转换成 字典
- # {}
- # {'id': '1'}
-
- print(request.args.get("id")) # 获取URL中的参数
- # None 没有参数的时候就是None
- # 1
-
- # print(request.args["id"]) # 获取URL中的参数
- # 1
- # 字典索引取不到值的时候 ,会出现keyerror
-
-
-
- print(request.environ) # 获取请求原始信息
- # {'wsgi.version': (1, 0), 'wsgi.url_scheme': 'http', 'wsgi.input': <_io.BufferedReader name=1140>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.run_once': False, 'werkzeug.server.shutdown': <function WSGIRequestHandler.make_environ.<locals>.shutdown_server at 0x000001F2C1CD8378>, 'SERVER_SOFTWARE': 'Werkzeug/0.15.4', 'REQUEST_METHOD': 'GET', 'SCRIPT_NAME': '', 'PATH_INFO': '/login', 'QUERY_STRING': '', 'REQUEST_URI': '/login', 'RAW_URI': '/login', 'REMOTE_ADDR': '127.0.0.1', 'REMOTE_PORT': 14611, 'SERVER_NAME': '127.0.0.1', 'SERVER_PORT': '5000', 'SERVER_PROTOCOL': 'HTTP/1.1', 'HTTP_HOST': '127.0.0.1:5000', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_CACHE_CONTROL': 'max-age=0', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9,en;q=0.8', 'HTTP_COOKIE': 'sessionid=wnuu61vo39ha2rnhjly8tturem306js3; csrftoken=dBlvd2yERl2dy9Oe7JoPLWer7aaOf35nx83lvoruaY0NOkl3T747KlIo5YwZ7026', 'werkzeug.request': <Request 'http://127.0.0.1:5000/login' [GET]>}
-
- print(request.base_url) # 获取URL头,不包含参数
- # http://127.0.0.1:5000/login
-
- print(request.json) # 毁三观 1 请求头中 Content-type:application/json 数据序列化 request.json
- # None
-
- print(request.data) # 毁三观 2 请求头中 Content-type 不包含 Form or data
- # b''
-
- print(request.headers) # 请求头中的数据
- # Host: 127.0.0.1:5000
- # Connection: keep-alive
- # Cache-Control: max-age=0
- # Upgrade-Insecure-Requests: 1
- # User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
- # Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
- # Accept-Encoding: gzip, deflate, br
- # Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
- # Cookie: sessionid=wnuu61vo39ha2rnhjly8tturem306js3; csrftoken=dBlvd2yERl2dy9Oe7JoPLWer7aaOf35nx83lvoruaY0NOkl3T747KlIo5YwZ7026
-
- return render_template("login.html")
-
- if request.method == "POST":
-
-
- print(request.method)
- # POST
-
-
-
- print(request.form)
- # Multidict 多重字典,得到字典套列表套元组的类型
- # ImmutableMultiDict([('username', '123'), ('pwd', '456')])
-
- print(request.form.to_dict())
- # {'username': '123', 'pwd': '456'}
-
-
-
- print(request.values) # 可以获取URL中的参数 也可以获取 FormData中的数据
- # CombinedMultiDict([ImmutableMultiDict([]), ImmutableMultiDict([('username', '123'), ('pwd', '456')])])
-
- print(request.values.to_dict())
- # {'username': '123', 'pwd': '456'}
-
-
-
- print(request.json) # 毁三观 1 请求头中 Content-type:application/json 数据序列化 request.json
- # None
-
- print(request.data) # 毁三观 2 请求头中 Content-type 不包含 Form or data 原始请求体数据
- # b''
-
-
- print(request.headers)
- # Host: 127.0.0.1:5000
- # Connection: keep-alive
- # Content-Length: 235
- # Cache-Control: max-age=0
- # Origin: http://127.0.0.1:5000
- # Upgrade-Insecure-Requests: 1
- # Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1BWoxZMCbTbU3Koy
- # User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
- # Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
- # Referer: http://127.0.0.1:5000/login
- # Accept-Encoding: gzip, deflate, br
- # Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
- # Cookie: sessionid=wnuu61vo39ha2rnhjly8tturem306js3; csrftoken=dBlvd2yERl2dy9Oe7JoPLWer7aaOf35nx83lvoruaY0NOkl3T747KlIo5YwZ7026
-
- # print(request.files.get("my_file"))
- #
- # my_file = request.files.get("my_file")
- # # fp = os.path.join("templates",my_file.filename)
- # my_file.save(my_file.filename)
-
-
- # 获取文件的数据
-
- print(request.files)
- # ImmutableMultiDict([('my_file', <FileStorage: '1.jpg' ('image/jpeg')>)])
- # 文件只在File 里显示
- # Form中不包含
-
- print(request.files.get("my_file"))
- # <FileStorage: '1.jpg' ('image/jpeg')>
-
- my_file = request.files.get("my_file")
- # my_file.save(my_file.filename)
- # 保存到本地的
-
- # 可以指定路径 用os模块
- fq = os.path.join("templates", my_file.filename)
- my_file.save(fq)
-
- username = request.form.get("username")
- password = request.form["pwd"]
- # Get 和索引都能拿到值
-
- if username == "123" and password == "456":
- return "登录成功"
- else:
- return "登录失败"
-
-
- # 如果包导入的话,if __name__下面不会执行
- if __name__ == '__main__':
- app.run()
3.2:login.html
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Title</title>
- <link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
-
- </head>
- <body>
-
- <form action="/login" method="post" enctype="multipart/form-data">
- 用户名: <input type="text " name="username">
- 密码: <input type="password" name="pwd">
- <input type="file" name="my_file">
- <input type="submit">
- </form>
-
-
-
- <script src="jquery-3.4.1.js"></script>
- <script>
-
- </script>
- </body>
- </html>
四:Jinja2和高级用法
-
- 4.Jinja2
- {{}} 引用 or 执行
- {%%} 逻辑语法 if else for
4.1:jinja2.py
- from flask import Flask, render_template,request,redirect,Markup
-
- STUDENT = {'name': 'Ivan', 'age': 38, 'gender': '中'}
-
- STUDENT_LIST = [
- {'name': 'Sail', 'age': 38, 'gender': '中'},
- {'name': 'Ivan', 'age': 73, 'gender': '男'},
- {'name': 'VS', 'age': 84, 'gender': '女'}
- ]
-
- STUDENT_DICT = {
- 1: {'name': 'Sail', 'age': 38, 'gender': '中'},
- 2: {'name': 'Ivan', 'age': 73, 'gender': '男'},
- 3: {'name': 'VS', 'age': 84, 'gender': '女'},
- }
-
- app = Flask(__name__)
- app.config["DEBUG"] = True
-
-
- @app.template_global()
- # 把ab函数传到前端了
- def ab(a,b):
- return a+b
-
-
-
- @app.route("/jija")
- def jija():
- my_in = Markup("<input type='text' name='uname'>")
- return render_template("jija.html",
- stu_info=STUDENT,
- stu_list=STUDENT_LIST,
- stu_dict=STUDENT_DICT,
- m=my_in
- )
-
-
- if __name__ == '__main__':
- app.run("127.0.0.1", 9999)
4.2:jinja2.html
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- {{ stu_info }}
-
- <table border="1px">
- <tr>
- <td>name</td>
- <td>age</td>
- <td>gender</td>
- </tr>
- <tr>
- <td>{{ stu_info.name }}</td>
- <td>{{ stu_info.get("age") }}</td>
- <td>{{ stu_info["gender"] }}</td>
- </tr>
-
- </table>
-
- <br/>
-
- {{ stu_list }}
-
- <table border="1px">
- <tr>
- <td>name</td>
- <td>age</td>
- <td>gender</td>
- </tr>
-
- ```
- {% for foo in stu_list %}
- <tr>
- <td>{{ foo.name }}</td>
- <td>{{ foo.get("age") }}</td>
- <td>{% if foo["gender"] !="男" and foo["gender"] !="女" %}
- 女
- {{ foo["gender"] }}
- {% endif %}
-
- </td>
- </tr>
- {% endfor %}
- ```
-
- </table>
- <br/>
-
- {{ stu_dict }}
-
- <table border="1px">
- <tr>
- <td>id</td>
- <td>name</td>
- <td>age</td>
- <td>gender</td>
- </tr>
- <tr>
- {% for id,s in stu_dict.items() %}
- <td>{{ id }}</td>
- <td>{{ s.name }}</td>
- <td>{{ s.get("age") }}</td>
- <td>{{ s["gender"] }}</td>
- </tr>
- {% endfor %}
-
- </table>
-
- <br/>
- {{ m }}
-
- <br/>
- {% macro my_input(na,ty) %}
- <input type="{{ ty }}" name="{{ na }}">
- {% endmacro %}
-
- {{ my_input("uname","text") }} # macro 需要启动才生产输入框
-
-
-
- <br/>
- {#{{ ab(1,2) }}#}
-
- </body>
- </html>
-
五:session
- 5.Flask中的Session 不是三方组件 //Flask-Session
- from flask import session
-
- session 交由客户端保管机制
- # eyJ1c2VybmFtZSI6IjEyMyJ9.XSVpHA.W0NfiCmW-lsTV0mvQI7mx2mf1Wo
- # .eJyrViotTi3KS8xNVbJSMjQyVtKBCxhiiBhhiBhjiJhgiJhiiJhBRWoBMFYkPg.XSVsaA.9merwNdTg3ZkZrdTumYRG7x8x7Y
- # .eJyrViotTi3KS8xNVbJSMjQyVtKBCxhiiBhhiBhjiJhgiJhiiJhBRWoBMFYkPg.XSVsvg.6OqcN7CR6nrT2BtE-w1kBAr3xPo
- # .eJxNzL0OgCAMBOB36exAoRTjs7jwUzcdNEzGdxckMV1u-e7uhnrJecRdYIG1eqS5pWCB6RccZDGtlQSjIvsRBxtbwZEmN8gZ21czK6JBiamtQhZF_qPAuR-WookH-dQO_WYiPC-8zDp8.XSVtLw.7I-z1bsqiWFln3cipbrVOpEE33g
-
- 反序列化机制 -
- 当客户端发起请求 - request 带上 Cookie - Cookie中有session的加密字符串 - Flask 收到Session加密字符串 - 通过secret_key解密session的加密字符串 - 获得 {username:123}
-
- 序列化机制 - 开启session - session["username"] = uname
- 先创建一个字典 {username:123} 接下来 通过secret_key + 时间戳 + 签名 加密 形成
- # eyJ1c2VybmFtZSI6IjEyMyJ9.XSVpHA.W0NfiCmW-lsTV0mvQI7mx2mf1Wo session的加密字符串
5.1:session.py
- from flask import Flask, session, request, render_template, redirect
-
- app = Flask(__name__)
- app.debug = True
- app.secret_key = "adfnaskjfnakjs"
-
- STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'}
-
- STUDENT_LIST = [
- {'name': 'Old', 'age': 38, 'gender': '中'},
- {'name': 'Boy', 'age': 73, 'gender': '男'},
- {'name': 'EDU', 'age': 84, 'gender': '女'}
- ]
-
- STUDENT_DICT = {
- 1: {'name': 'Old', 'age': 38, 'gender': '中'},
- 2: {'name': 'Boy', 'age': 73, 'gender': '男'},
- 3: {'name': 'EDU', 'age': 84, 'gender': '女'},
- }
-
-
- @app.route("/login", methods=["POST", "GET"])
- def login():
- if request.method == "GET":
- return render_template("login.html")
-
- uname = request.form.get("username")
- pwd = request.form.get("pwd")
-
- if uname == '123' and pwd == '123':
- session['username'] = uname
- return "登陆成功"
- else:
- return "登录失败"
-
-
- @app.route("/detail")
- def detail():
- if session.get("username"):
- return render_template("jija.html",
- stu_info=STUDENT,
- stu_list=STUDENT_LIST,
- stu_dict=STUDENT_DICT, )
-
- else:
- return redirect("/login")
-
-
- if __name__ == '__main__':
- app.run("127.0.0.1", 9999)
-
-
-
-
5.2:login.html
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Title</title>
- <link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
-
- </head>
- <body>
-
- <form action="/login" method="post" enctype="multipart/form-data">
- 用户名: <input type="text " name="username">
- 密码: <input type="password" name="pwd">
- <input type="file" name="my_file">
- <input type="submit">
- </form>
-
-
-
- <script src="jquery-3.4.1.js"></script>
- <script>
-
- </script>
- </body>
- </html>