一、框架对比

  • Django —— 教科书式框架

    • 优势:组件全,功能全,教科书

    • 劣势:占用资源,创建复杂度高

  • Flask —— 以简单为基准开发,一切从简,能省则省

    • 优势:轻,块

    • 劣势:先天不足,第三方组件稳定性较差

Django Flask
Admin —— Model 原生无
Model 原生无
Form 原生无
Session 有 —— 颠覆认知操作

二、Flask入门

  • 下载安装

    • 下载:pip install Flask

    • 注意:不要使用工具中的插件创建 Flask 项目

  • 三行代码启动Flask项目

    from flask import Flask
    app = Flask(__name__)
    app.run()

三、Flask的请求和响应

3.1 Flask中的响应Response

  • 与django对比

    Django Flask 返回
    HttpResponse("hello") "hello" 字符串
    render(request,"html",{"k":v}) render_template("html",k=v) html页面
    redirect("/") redirect("/") 重定向
    JsonResponse({"k":v}) jsonify({"k":v}) 标准的json字符串
    • 以上是web框架的Response三剑客

  • 返回字符串 —— string

    from flask import Flask
    app = Flask(__name__)
    @app.route("/")
    def home():
    return "hello World I am Flask"
    app.run()
  • 返回html页面 —— string

    from flask import Flask, render_template
    app = Flask(__name__)
    @app.route("/index")
    def index():
    return render_template("index.html")
    app.run()
  • 返回重定向 —— string

    from flask import Flask, redirect
    app = Flask(__name__)
    @app.route("/login")
    def login():
    return redirect("/index")
    app.run()
  • 返回文件内容 —— Response instance

    • send_file():读取并返回文件内容,自动识别文件类型,Content-type中添加类型,即,Content-type:文本类型

    • 浏览器特性:

      • 可识别的Content-type,会自动渲染

      • 不可识别的Content-type,会自动下载

    from flask import Flask, send_file
    app = Flask(__name__)
    @app.route("/get_file")
    def get_file():
    # 返回文件内容,自动识别文件类型,Content-type中添加文件类型,Content-type:文件类型
    return send_file("2.exe")
    app.run()
  • 返回标准格式的json字符串 —— string

    • jsonify():返回标准格式的json字符串,本质:先序列化json的字典,Content-type中加入Application/json,Flask1.1.1 直接返回字典格式,相当于自动执行jsonify

    from flask import Flask, send_file
    app = Flask(__name__)
    @app.route("/get_json")
    def get_json():
    d = {"k":"v"}
    # 返回标准Json格式字符串 API接口
    return jsonify(d)
    app.run()

3.2 Flask中的请求Request

  • 与django对比

    Django Flask Flask中的含义
    request.method request.method 获取请求方式
    request.GET request.args 获取URL中的数据
    request.POST request.form 获取FormData中的数据 ,也就是所谓的Form标签
    request.FILES request.files 获取request中的文件,返回FileStorage中,存在save(保存文件)和filename(原始文件名)
      request.json 请求中Content-Type:application/json,请求体中的数据被序列化到 request.json中,以字典的形式存放
      request.data 请求中Content-Type中不包含Form或FormData,保留请求体中的原始数据,bytes类型
    request.path_info request.path 请求路径 路由地址
    request.get_full_patch() request.url 访问请求的完整路径包括 url参数
    request.get_host() request.host 主机位 127.0.0.1:5000
    request.COOKTES request.cookies 字典获取浏览器请求时带上的Cookie
    • 注意:request.values,获取url和FormData中的数据,敏感地带(url和FormData中存在相同的key时会出错)

import os
from flask import Flask, request, render_template
# request 请求上下文管理
app = Flask(__name__)

@app.route("/login",methods=["GET","POST"])
def login():
# print(request.args.to_dict())
# print(request.host)
# print(request.path)
# print(request.url)
# print(request.cookies)
# 优先判断 请求方式
# 如果是 GET 请求 返回登录页面
if request.method == "GET":
return render_template("login.html")
# 如果是 POST 请求 获取用户名密码 校验
else: # 405 请求方式不被允许
my_file = request.files.get("my_file")
filename = my_file.filename # 获取原始文件名
file_path = os.path.join("avatar",filename)
my_file.save(file_path)
print(request.form.to_dict()) # form - FormData
if request.form.get("username") == "YWB":
return "Login OK!"
return "Login 不OK!"

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

示例

四、 Jinja2:template语言

  • {{ }} 引用或执行

  • {% %} 逻辑引用

    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': '女'},
    }
    from flask import Flask, render_template, Markup
    app = Flask(__name__)

    @app.template_global()
    def ab(a,b):
    return a+b

    @app.route("/")
    def home():
    return render_template("stu.html",stu=STUDENT,stu_l = STUDENT_LIST,stu_d = STUDENT_DICT)

    @app.template_global()
    def my_input(na,ty):
    s = f"<input type='{ty}' value='{na}'>"
    return Markup(s)

    if __name__ == '__main__':
    app.run()
    <p>{{ ab(50,60) }}</p>
    
    {{ stu }}
    <table border="1px">
    <tr>
    <td>name</td>
    <td>age</td>
    <td>gender</td>
    </tr>
    <tr>
    <td>{{ stu.name }}</td>
    <td>{{ stu["age"] }}</td>
    <td>{{ stu.get("gender") }}</td>
    </tr>
    </table> {{ stu_l }}
    <table border="1px">
    <tr>
    <td>name</td>
    <td>age</td>
    <td>gender</td>
    </tr>
    {% for student in stu_l %}
    <tr>
    <td>{{ student.name }}</td>
    <td>{{ student["age"] }}</td>
    <td>
    {% if student.get("gender") != "男" and student.get("gender") != "女" %}

    {% else %}
    {{ student.get("gender") }}
    {% endif %}
    </td>
    </tr>
    {% endfor %}
    </table> {{ stu_d }}
    <table border="1px">
    <tr>
    <td>id</td>
    <td>name</td>
    <td>age</td>
    <td>gender</td>
    </tr>
    {% for skey,svalue in stu_d.items() %}
    <tr>
    <td>{{ skey }}</td>
    <td>{{ svalue.get("name") }}</td>
    <td>{{ svalue.get("age") }}</td>
    <td>
    11111
    </td>
    </tr>
    {% endfor %}
    </table>

    stu.html

五、Flask的知识点

5.1 Flask中的session

  • 基于请求上下文管理机制

    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': '女'},
    }
    from flask import Flask, render_template, request, session, redirect
    app = Flask(__name__)
    # app.config["DEBUG"] = True
    app.debug = True
    app.secret_key = "!@#$%^(*&^%$#@#$%&*(^$WQ*(^EWET*^EWEU" def war(func): # func = home
    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 # war(home) -> inner == == home
    # 先要经过一次校验 才能执行或不执行视图函数
    def home():
    # 校验用户登录 session
    #如果session。get(“user”) 存在
    # 如果不存在 返回Login
    return render_template("stu.html",stu=STUDENT,stu_l = STUDENT_LIST,stu_d = STUDENT_DICT) @app.route("/a")
    def homea():
    # 校验用户登录状态?
    # 校验session中有没有 user Key
    if session.get("user"):
    inp = Markup("<input type='submit' value='后端给返回的按钮'>")
    return render_template("my_a.html", btn=inp)
    # 校验失败
    # 跳转login
    else:
    return redirect("/login") @app.route("/login",methods=["GET","POST"])
    def login():
    # 当请求方式为 GET 的时候
    if request.method == "GET":
    # eyJ1c2VyIjoiYWxleGFuZGVyLmRzYi5saSJ9.XUfYMw.o8oZX2GMC-kjZPWBkyRuUeSMp4M
    # 交由客户端保管机制
    # {"user":"alexander.dsb.li"}
    # Flask理念 - 一切从简 为服务器减轻压力
    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)

5.2 Flask中的路由

  • @app.route()

    • 参数:

      • rule:路由地址,例,"/login"

      • methods:允许进入视图函数的请求方式

      • endpoint:mapping ,路由地址和endpoint之间的mapping,路由地址和视图函数之间还有一个mapping,注意,endpoint在同一个app中不能出现重复,默认值是视图函数名

      • defaults:默认路由参数

      • strict_slashes:是否严格遵循路由匹配规则

      • redirect_to:永久重定向 ,308和301

from flask import Flask,request,url_for
# url_for用于对endpoint设置的名称的反向获取url
app = Flask(__name__) @app.route("/a",methods=["GET","PoSt","options","abc"],endpoint="end_homea" ,defaults={"count":20},strict_slashes=True,redirect_to="/")
def homea(count):
# print(url_for("end_homea"))
# 如果在蓝图里面,要使用url_for("蓝图标识".endpoint)
# 如文件名为app01,则url_for("app01.end_homea")
count = request.args.get("count",count)
return f"200OK!{count}"

示例

  • 动态参数路由

    • 可以分页,获取文件,解决分类,解决正则路由问题

    from flask import Flask,request,url_for
    # url_for用于对endpoint设置的名称的反向获取url
    app = Flask(__name__) @app.route("/get_img/<filename>")
    def get_img(filename):
    filepath = os.path.join("img", filename)
    return send_file(filepath) # 访问地址 : http://127.0.0.1:5000/info/1
    @app.route("/info/<int:nid>", methods=["GET", "POST"], endpoint="r_info")
    def student_info(nid):
    print(url_for("r_info",nid=2)) # /info/2,反向url时也要加上参数
    return f"Hello Old boy {nid}" # Python3.6的新特性 f"{变量名}"

5.3 Flask初始化配置

  • 常用配置:

    • template_folder:模板文件存放路径

    • static_folder:静态文件存放目录,默认值是static

    • static_url_path:静态文件访问路径,默认值是/ + static_folder

from flask import Flask
app = Flask(__name__,template_folder="templatess",
static_folder="static",static_url_path="/futeng")
# static == 你的家
# /static == 回家路
# /futeng == 富腾路

示例

5.4 Flask实例配置

  • Flask实例配置,即app的配置,可以在app.default_config中查看

    # 在setting.py中,写配置对应的类
    import hashlib,time
    class DebugConfig(object):
    DEBUG = True
    SECRET_KEY = "#$%^&*($#$%^&*%$#$%^&*^%$#$%"
    PERMANENT_SESSION_LIFETIME = 3600
    SESSION_COOKIE_NAME = "I am Not Session" class TestConfig(object):
    TESTING = True
    SECRET_KEY = hashlib.md5(f"{time.time()}#$%^&*($#$%^&*%$#$%^&*^%$#$%{time.time()}".encode("utf8")).hexdigest()
    PERMANENT_SESSION_LIFETIME = 360000
    SESSION_COOKIE_NAME = "#$%^&*($#$%^&*%$#$%^&*^%$#$%" # 在可执行文件中,调用
    from flask import Flask
    from setting import DebugConfig,TestConfig app = Flask(__name__)
    app.config.from_object(DebugConfig)
    # 或 app.config.from_object(TestConfig)

5.5 Flask的蓝图

  • 蓝图:Blueprint,不能被run的Flask实例 不存在Config

    # 在可执行文件中,调用
    from flask import Flask
    from users import bp
    from car_users import car_bp app = Flask(__name__)
    app.register_blueprint(bp)
    app.register_blueprint(car_bp)
    from flask import Blueprint
    bp = Blueprint("app01",__name__) @bp.route("/add_user")
    def add_user():
    return "添加用户" @bp.route("/find_user")
    def find_user():
    return "查看用户" @bp.route("/drop_user")
    def drop_user():
    return "删除用户" @bp.route("/up_user")
    def up_user():
    return "修改用户"

    users.py

    from flask import Blueprint
    car_bp = Blueprint("app02",__name__,url_prefix="/car")
    # 参数url_prefix是为了区分users.py和car_users.py中的相同路由
    # 使用url_prefix后,访问时,要在原来路由前加上url_prefix设置的路径 @car_bp.route("/add_user")
    def add_user():
    return "car添加用户" @car_bp.route("/find_user")
    def find_user():
    return "car查看用户" @car_bp.route("/drop_user")
    def drop_user():
    return "car删除用户" @car_bp.route("/up_user")
    def up_user():
    print("I am vf")
    return "car修改用户"

    car_users.py

5.6 Flask特殊装饰器

  • @app.before_request:在请求进入视图函数之前 做出处理

  • @app.after_request:在响应返回客户端之前,结束视图函数之后

@app.before_request
def be1():
print("I am Be1")
# return "第一个请求你就过不去" # 5种 @app.before_request
def be2():
print("I am Be2")
# return "第二个请求过不去了" # 5种 @app.after_request
def af1(res):
print("I am af1")
return res @app.after_request
def af2(res):
print("I am af2")
return res

示例

    • be+af 请求生命周期:

      • 正常:be1 -> be2 -> vf -> af2 -> af1

      • 异常:be1 -> af2 -> af1

      • 注意:只要有响应返回 , af全部执行

  • @app.errorhandler:重定义错误页面

@app.errorhandler(404)        # 只能是 4xx,5xx
def error404(error_message):
print(error_message)
# return redirect("https://www.autohome.com.cn/111232130/#pvareaid=33112794r5454") # 5种类型

示例

5.7 Flask的CBV

  • CBV:继承 MethodView 让当前的 class 可以成为视图类

    from flask import Flask
    app = Flask(__name__) class Login(views.MethodView):
    def get(self,*args,**kwargs):
    return "I am Get" def post(self,*args,**kwargs):
    pass app.add_url_rule("/login",
    endpoint="my_login", # 可以不设置endpoint
    view_func=Login.as_view(name="loginlogin") # view_func.__name__="loginlogin"
    )

六、Flask组件:Flask-Session

  • 下载:pip install Flask-Session

  • 使用:

    from flask import Flask
    from flask_session import Session
    from redis import Redis app = Flask(__name__)
    app.config["SESSION_TYPE"] = "redis"
    app.config["SESSION_REDIS"] = Redis(host="192.168.12.87",port=6379,db=10)
    # app.session_interface # Flask 利用 session_interface 选择 Session 的存放位置 和 存放机制
    # app.default_config Session(app)

七、Flask总结

  1. 下载:pip install Flask

  2. 启动:

    from flask import Flask
    app = Flask(__name__)
    app.run("0.0.0.0",9527) # 监听地址 监听端口
  3. response

    # Flask 三剑客
    return "" # 返回字符串 HTTPResponse
    return render_template("index.html") # 返回模板 依赖MarkupSafe 默认存放路径:templates
    return redirect("/login") # 响应头中加入 - location:重定向
    # Flask 特殊Response
    return send_file(文件名称或文件路径+文件名称) # 打开并返回文件内容 自动识别文件类型 响应头 Content-Type:文件类型
    return jsonify({k:v}) # 返回标准格式的json字符串 响应头中 Content-Type:application/json
    # Flask 1.1.1中直接返回dict 本质上是在运行jsonify
  4. request

    from flask import request
    request.form # 获取FormData中的数据 to_dict() 类似字典类型 .get() ["key"] KeyError
    request.args # 获取URL中的数据 to_dict() 类似字典类型 .get() ["key"] KeyError
    request.json # 请求头中 Content-Type:application/json 存放字典
    request.data # 请求头中 Content-Type没有Form FormData 存放bytes类型 request.method # 请求方式
    request.cookies # 浏览器的cookie键值对
    request.headers # 请求头
    request.path # 路由地址 请求地址
    request.url # 请求全部地址
    request.host # 主机位
  5. session 交由客户端保管机制 保管一串儿加密字符串

    from flask import session
    app.config["SECRET_KEY"] = "@#$%^&*(()*&^%$#*&^&%^&*)"
    session["key"] = "value"
  6. 路由配置 route

    @app.route(
    rule, # 路由地址
    endpoint, # mapping 名称对应路由地址 url_for 反向推算路由地址 url_for(endpoint)
    methods, # 允许进入视图函数的 请求方式
    redirect_to, # 永久重定向 301 308
    strict_slashes, # 是否严格遵循路由匹配规则
    defalut, # 默认参数
    ) @app.add_url_rule(
    rule,
    view_func, # 视图函数
    ) # 动态参数路由
    @app.route("/get_file/<filename>")
    def get_file(filename):
    pass
  7. 初始化配置

    Flask(__name__,
    template_folder, # 模板存放文件
    static_folder, # 静态文件存放目录
    static_url_path, # 静态文件访问路径
    )
  8. config

    class DebugConfig(object):
    DEBUG = True
    ... app.config.from_object(DebugConfig)
  9. 蓝图 Blueprint 当成不能被 run 的 Flask 实例

    from flask import Blueprint
    bp = Blueprint("bp",__name__,
    url_perfix, # url前缀
    )
    @bp.route("/mybp",endpont="")
    @bp.add_url_rule
    @bp.before_request
    @bp.after_request
    @bp.errorhandler(http错误码) url_for("蓝图标识".endpoint)
    url_for("bp.666") app.register_blueprint(bp)
  10. 特殊装饰器

    @app.before_request    # 在请求进入视图函数之前,做出处理
    @app.after_request # 在结束视图函数之后,响应客户端之前
    @app.errorhandler(http错误码) # 重定向错误信息
    def error404(errorMessage):
    pass
  11. CBV

    from flask import views
    class Login(views.MethodView):
    def get(self,*args,**kwargs):
    pass
    app.add_url_rule("/login",endpoint=None,view_func=Login.as_view(name="loginlogin"))
    # name是当前视图函数名,必须唯一,因为他是endpoint

浅谈 Flask 框架的更多相关文章

  1. 浅谈flask源码之请求过程

    更新时间:2018年07月26日 09:51:36   作者:Dear.   我要评论   这篇文章主要介绍了浅谈flask源码之请求过程,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随 ...

  2. 手撸ORM浅谈ORM框架之基础篇

    好奇害死猫 一直觉得ORM框架好用.功能强大集众多优点于一身,当然ORM并非完美无缺,任何事物优缺点并存!我曾一度认为以为使用了ORM框架根本不需要关注Sql语句如何执行的,更不用关心优化的问题!!! ...

  3. 手撸ORM浅谈ORM框架之Add篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  4. 手撸ORM浅谈ORM框架之Update篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  5. 手撸ORM浅谈ORM框架之Delete篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  6. 手撸ORM浅谈ORM框架之Query篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  7. 【SSH学习笔记】浅谈SSH框架

    说在前面 本学期我们有一门课叫做Java EE,由陈老师所授,主要讲的就是Java EE 中的SSH框架. 由于陈老师授课风格以及自己的原因导致学了整整一学期不知道在讲什么,所以才有了自己重新学习总结 ...

  8. 浅谈angular框架

    最近新接触了一个js框架angular,这个框架有着诸多特性,最为核心的是:MVVM.模块化.自动化双向数据绑定.语义化标签.依赖注入,以上这些全部都是属于angular特性,虽然说它的功能十分的强大 ...

  9. 浅谈 Web框架

    一.Web框架本质 所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端 二.Web框架功能 socket收发消息 —— wsgiref(测试).uwsgi(线上 ...

随机推荐

  1. 使用Fiddler进行HTTP流量分析

    - 安装 Fiddler是一款免费软件,可以到其官网下载,地址是https://www.telerik.com/fiddler,也可以从我的网盘中下载,发送"fiddler"获取下 ...

  2. NumPy实现数组的拼接和分裂

    一.数组的拼接 import numpy as np x=np.array([,,]) x2=np.array([,,])np.concatenate([x,x2]) 输出:array([1, 2, ...

  3. Python的日志功能

    python自带的logging是日志处理模块,可以记录日志,并输出到控制台和文件等.日志分5个级别:DEBUG:调试信息,权重10INFO:一般信息,权重20WARNING:警告信息,权重30ERR ...

  4. [MySQL] 解决Error 1698: Access denied for user 'root'@'localhost'

    当程序中使用root账号连接mysql时报以下错误,但是使用命令行是可以正常连接的,那么就查询下mysql数据库的user表,查看下当前用户的密码加密方式,看看是不是unix_socketMariaD ...

  5. AtCoder - 2565(思维+暴力)

    题意 https://vjudge.net/problem/AtCoder-2565 将一个H*W的矩形切成三份,每一次只能水平或者垂直切,问最大块的面积-最小快的面积 的最小值是多少. 思路 先枚举 ...

  6. C学习笔记(6)--- 共用体,位域深入

    1.共用体(Union): 共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型.您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值.共用体提供了一种使用相同的内存位置 ...

  7. Linux文件基本命令

    Linux文件基本命令学习 操作技巧: 输入文件/目录/命令的前几个字母之后,按下tab键,则自动补全 按上/下,回滚曾经用过的命令 不想执行命令使用:crtl + c 基础命令: ls(查看) 基础 ...

  8. vue 组件之纯表格渲染--没有事件交互

    组件 名称小写==> 用-链接 02===> 属性==> empty-text="暂无数据" 当表格中没有数据 就会显示 暂无数据 <el-table-co ...

  9. 27.Java基础_多态

    父类对象引用子类对象: Animal a=new Cat(); 多态中的转型 public class Animal { public void eat(){ System.out.println(& ...

  10. c# WF 第1节 创建winform程序

    本节内容: 1:vs的RAD 2:WinForm的创建简介 3:创建窗口与控制台程序文件的对比 4:窗口文件内容 5:winform怎么运行 6:winform的实质 1:vs的RAD 2:WinFo ...