Flask 轻便的web框架-1
内容简述
1.Flask与django对比
-
框架对比
Django Flask Admin -Model 原生无 Model 原生无 Form表单 原生无 Session 有--->特殊 第三方组件特别多 -
Flask:宗旨:以简单为基准 开发一切从简 能省则省
2.Django与Flask的优势劣势对比:
-
django:
- 优势:组件全,功能全,教科书
- 劣势:占用资源,创建复杂度较高
-
Flask:
- 优势:轻量级,速度快
- 劣势:先天不足,第三方组件稳定性较差
3.入门Flask
- pip3 install Flask 不要使用工具中的插件创建Flask项目
- 三行代码启动Flask项目
-
附属模块:
4.一个简单Flask:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Hello world!"
if __name__ == '__main__':
app.run()
- route:一个装饰器,用于为给定的URL规则注册视图函数。
5.web框架的Response三剑客:
- HTTPResponse
- redirect
- render
Content-Type:text/html 为text文本类型,要用html渲染
- render_template
- send_file
- jsonify
- render_template()
from flask import Flask, render_template, redirect, send_file, jsonify
app = Flask(__name__)
@app.route("/")
def home():
return "Hello World I am Flask"
@app.route("/index")
def index():
return render_template("index.html")
@app.route("/login")
def login():
return redirect("/index")
@app.route("/get_file")
def get_file():
return send_file("app01.py")
@app.route("/get_json")
def get_json():
#alt + enter
return jsonify("hello json")#返回标准Json格式字符串
app.run()
- 母版配置
- 项目下新建templates,点击鼠标右键,Mark Directory as--->Template Folder
6.send_file()
-
返回是一个instance类型
-
会自动识别文件类型,Content-type中添加文件类型,Content-type:文件类型
-
保留当前文件格式
-
示例:
from flask import Flask,send_file app = Flask(__name__) @app.route("/") def TestDemo(): return send_file("demo3.py")#返回文件内容,字符串 @app.route("/get_file") def get_file(): return send_file("文咏珊.jpg")#send_file会自动是被文件类型,Content-type中添加文件类型 @app.route("/get_music") def get_music(): return send_file("音乐.mp3")#send_file会自动是被文件类型,Content-type中添加文件类型 @app.route("/get_video") def get_video(): return send_file("电影.mp4")#send_file会自动是被文件类型,Content-type中添加文件类型 if __name__ == '__main__': app.run()
-
浏览器特性 可识别Content-type 自动渲染
-
不可识别的Content-type 会自动下载
- content_type:image/jpeg 返回类型为一张图片
- content_type:audio/mpeg:返回类型为一张图片
- content_type :video.mp4:返回类型为一个电影
- application/x-msdownload:返回一个可下载类型
- Content-Type: application/json 返回一个Json
7.jsonify() str
- 返回标准格式的json字符串 先序列化json的字典,Content-type中加入Application/json
- flask 1.1.1版本中可以直接返回字典格式无序jsonify
from flask import Flask,send_file,jsonify
app = Flask(__name__)
@app.route("/get_json")
def get_json():
dic = {"k1":"v1"}
return jsonify(dic)#return dic 是一样的
if __name__ == '__main__':
app.run()
-
文件特性:
- 凡是二进制文件的开头,都设置文件类型
-
浏览器特性:
- 可根据文件开头描述文件类型。识别的Content-type会自动渲染
- 当不可识别Content-type 会自动下载
FLASK 1.1.1之后的版本可以直接返回字典等数据类型,flask会自动帮你json序列化
8.flask中的request
-
request.method 获取请求方式
-
request.form 获取FormData中的数据,也就是form标签
from flask import Flask,request,render_template,Markup # request:请求上下文管理,机制的实现 app = Flask(__name__) @app.route("/login",methods=["GET","POST"]) def login(): # 如果是get请求 返回登录页面 if request.method == "GET": return render_template("login.html") #如果是post请求,获取用户名密码 校验 else:#405 表示请求方式不被允许 # 表示直接可将ImmutableMultiDict对象转换成字典 print(request.form.to_dict()) # 这里form指的是浏览器提交的Form表单数据(FormData) print("request.form------>", request.form)# ImmutableMultiDict([('username', 'xjk'), ('password', '123')]) print(request.form["username"])#法1:获取用户名 print(request.form.get("username"))#法2:获取用户名 if request.form.get("username") == "ywb": return "Login ok!" return "Login 失败" if __name__ == '__main__': app.run()
-
request.args 获取URL中的数据 to_dict()
#http://127.0.0.1:5000/get_json?id=1 def get_json(): print(request.args.to_dict())#{'id': '1'} dic = {"k1":"v1"} return dic
-
request.values 获取url和FormData中的数据(to_dict() url会覆盖FormData)
-
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 主机位
-
request.cookies 字典获取浏览器请求时带上cookies
9.文件上传
- 注意前端form表单加
enctype="multipart/form-data"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="my_file">
<button type="submit">提交</button>
</form>
</body>
</html>
from flask import Flask, request, render_template
import os
app = Flask(__name__)
@app.route("/upload",methods=["GET","POST"])
def upload():
#判断请求是方式
if request.method == "GET":
return render_template("upload.html")
if request.method == "POST":
my_file = request.files.get("my_file")
print(my_file,type(my_file))#<FileStorage: '文咏珊.jpg' ('image/jpeg')> <class 'werkzeug.datastructures.FileStorage'>
"""
stream=None,
filename=None,
name=None,
content_type=None,
content_length=None,
headers=None,
"""
print("stream-->",my_file.stream)#<tempfile.SpooledTemporaryFile object at 0x00000192D5D04BA8>
print("name-->",my_file.name)#my_file
print("content_type-->",my_file.content_type)#image/jpeg
print("headers-->",my_file.headers)#Content-Disposition: form-data; name="my_file"; filename="文咏珊.jpg"
filename = my_file.filename #获取原始文件名
file_path = os.path.join("avatar",filename)
my_file.save(file_path)#将文件内容存入指定路径下
return "上传完毕"
return "上传失败"
if __name__ == '__main__':
app.run(host="127.0.0.1",port="5000",debug=True)#debug可以在此设置,如果给定,启用或禁用调试模式。
或者:
app.debug = True
app.config["DEBUG"] = True
3选1均可
10jinja2
- Flask的模版语言
- {{ }} 引用或执行
- {%%} 逻辑引用
10.1函数在模版中应用
- 返回数值相加之和
@app.template_global()
def add_num(a,b):
return a+b
模版应用:<p>{{ add_num(50,60) }}</p>
- 返回html标签
from markupsafe import Markup
@app.template_global()
def my_input(na,ty):
s = f"<input type='{ty}' value='{na}'>"
return Markup(s)
模版应用:{{ my_input("上传","submit") }}
- 直接在模版书写----->宏指令
<div>密码:
{% macro my_input(na,ty) %}
<input type="{{ ty }}" name="{{ na }}">
{% endmacro %}
{{ my_input("pwd","password") }}
</div>
- 在模板中如何添加数据
obj.get('name')
obj["name"]
{%for skey,svalue in obj.items()%}
{%endfor%}
{%for skey in obj%}
{%endfor%}
- 示例:
<body>
{% for i in t %}
<div>{{ i }}</div>
{% endfor %}
<div>I am a index</div>
</body>
@app.route("/index")
def index():
rest = [1, 2, 3, 4, 5]
return render_template('index.html',t=rest)
12.flask中的session
- 基于请求上下文管理机制
#系统定义了全局变量
session = LocalProxy(partial(_lookup_req_object, "session"))
- 做一个flask的登录
- 导入模块:from flask import session
- 设置密钥:app.secret_key = "密钥内容"
- 登录成功设置session
from flask import Flask, render_template, Markup, request, session, redirect
app = Flask(__name__)
app.debug = True
app.secret_key = "!@#$%^(*&^%$#@#$%&*(^$WQ*(^EWET*^EWEU"
@app.route("/login",methods=["GET","POST"])
def login():
if request.method == "POST":
print(request.form)#ImmutableMultiDict([('username', 'admin'), ('password', '123')])
user = request.form.get("username","")
pwd = request.form.get("password","")
if user == "admin" and pwd == "123":
session["user"] = user#登录成功,给session设置值
return "登录成功"
#交由客户端保管机制
print(session.get("user"))
return render_template("login.html")
if __name__ == '__main__':
app.run()
13values的坑(慎用)
#my_login.html
<form action="?id=101&user=20" method="post">
账号:<input type="text" name="user">
密码:<input type="password" name="pwd">
<input type="submit" value="提交">
</form>
#函数
@app.route("/mlogin",methods=["GET","POST"])
def my_login():
if request.method == "GET":
return render_template("my_login.html")
if request.method == "POST":
print(request.values)
print(request.values.to_dict())
return "来了老弟"
#CombinedMultiDict([ImmutableMultiDict([('id', '101'), ('user', '20')]), ImmutableMultiDict([('user', 'wxx'), ('pwd', '123')])])
#{'user': '20', 'pwd': '123', 'id': '101'}
- 当url和form中的Key重名的话,form中的同名的key中value会被url中的value覆盖
14.给多个函数加同一个装饰器
-
法1:
import functools 在装饰器inner里加入@functools.wraps(func) functools.wraps(func)相当于保留元信息 如果不加,会报错: AssertionError: View function mapping is overwriting an existing endpoint function: inner 不加效果等同于inner = inner(detail()) 如果加了装饰器,效果等同于inner.__name__ = func.__name__ 其函数名字得以保留
-
示例:
def wrapper(func): @functools.wraps(func) def inner(*args,**kwargs): session_key = session.get("user") if session_key: ret = func(*args,**kwargs) return ret else: return redirect('/login') return inner
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库