Flask:初识

1 Flask介绍(轻量级的框架,非常快速的就能把程序搭建起来)

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

和django的比较
    django:无socket,依赖第三方模块wsgi,中间件,路由系统(CBV,FBV),视图函数,ORM。cookie,session,Admin,Form,Auth,缓存,信号,序列化。
    Flask:无socket,中间件(扩展),路由系统,视图(CBV)、第三方模块(依赖jinja2),cookie,session弱爆了

 

2 简单使用

2.1 安装

pip3 install flask

2.2 Werkzeug 简介

Werkzeug 是一个WSGI工具包,它可以作为一个web框架的底层库,它封装了很多web框架的东西,如Request,Response

#Flask依赖一个实现wsgi协议的模块:werkzeug
from werkzeug.wrappers import Request, Response

@Request.application
def hello(request):
    return Response('Hello World!')

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, hello)

2.3 flask快速使用

from flask import Flask

app = Flask(__name__) # 实例化产生一个Flask对象

# 将'/'路径和视图函数index的对应关系添加到路由中
# 装饰器加括号执行route,返回decorator函数内存地址,把index当做参数传给decorator函数执行
@app.route('/') 
def index():
    return 'Hello World!'

if __name__ == '__main__':
    # 不传参默认loaclhost, 5000端口
    # 最终调用的run_simple(),把Flask对象app传过去
    # werkzeug会执行app(),并传入request对象,执行app()--》触发Flask类的__call__方法
    app.run()

2.4 web框架三板斧

1 返回字符串类型的数据
# django用法:return HttpResponse('hello i am djanggo')
# flask用法: return 'hello i am flask'   直接返回字符串


2 返回html文件,即返回html渲染的页面
# django用法:return render(request, 'djangohtml.html')
# flask用法: return render_template('flask.html')
# 生成Flask对象时,初始化默认template_folder='templates',因此在根路径下建一个templates文件夹,存放html模板

# 模板语法传值
# django用法: return render(request, 'render_html.html',{'data': user_dict,'data2':123})
#              return render(request, 'render_html.html',locals()) 
# flask用法: return render_template('flask.html',data=user_dict,data2='egon') 直接key=val传值,不用字典

3 重定向
# django用法: return redirect('/home/') 可以跳转到其他url或自定义的路由
# redirect括号内可以直接写url,也可以直接写别名;但redirect只能反向解析不带参数的,如果别名需要额外传参,就必须使用reverse

# flask用法: return redirect('http://taobao.com/')

2.5 两种添加路由的方式

方式一:
@app.route('/index')  # @decorator
def index():
    return "Index"
    
    
方式二:
def index():
    return "Index"

# 路由的本质,endpoint是别名,如果不写,就用视图函数名作为别名;endpoint不能重名
app.add_url_rule('/index', view_func=index, endpoint='nl') 

2.6 Flask中装饰器应用

from flask import Flask,render_template,request,redirect,session
app = Flask(__name__)
app.secret_key = "sdsfdsgdfgdfgfh"

# 登录认证装饰器
def wrapper(func):
    def inner(*args,**kwargs):
        if not session.get("user_info"):
            return redirect("/login")
        ret = func(*args,**kwargs)
        return ret
    return inner

@app.route("/login",methods=["GET","POST"])
def login():
    if request.method=="GET":
        return render_template("login.html")
    else:
        # print(request.values)   #这个里面什么都有,相当于body
        user = request.form.get("user")
        pwd= request.form.get("pwd")
        if user=="zl" and pwd="123":
            session["user_info"] = user
            # session.pop("user_info")  #删除session
            return redirect("/index")
        else:
            # return render_template("login.html",**{"msg":"用户名或密码错误"})
            return render_template("login.html",msg="用户名或者密码错误")

# 装饰器执行顺序从上至下,匹配路由后才能进行认证
@app.route("/index",methods=["GET","POST"])
@wrapper
def index():
    # if not session.get("user_info"):
    #     return redirect("/login")
    return render_template("index.html")


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

2.7  请求响应相关 

# request
    - request.form         #POST请求
    - request.args         #GET请求,字典形式的
    - request.querystring  #GET请求,bytes形式的
    
# response
    - return render_tempalte()
    - return redirect()
    - return ""
    v = make_response(返回值)  #把返回的值包在了这个函数里面
    
# session
   - 存储在浏览器上(django的session默认存在数据库django_session表中),并且是加密的
   - 依赖于:secret_key
   - 设置:session['username'] = 'xxx'
   - 删除:session.pop('username', None)

 

案例:登录,显示用户信息

View Code
 from flask import Flask, render_template, request, redirect, session, url_for

app = Flask(__name__)
app.debug = True
app.secret_key = "sdsfdsgdfgdfgfh"  # 跟django的settings中的密钥一个意思,设置session的加密方式

USERS = {
    1: {'name': '张三', 'age': 18, 'gender': '男', 'text': '道路千万条'},
    2: {'name': '李四', 'age': 28, 'gender': '男', 'text': '安全第一条'},
    3: {'name': '王五', 'age': 38, 'gender': '女', 'text': '行车不规范'},
}


# 转换器<int:nid>,相当于有名分组的作用
@app.route('/detail/<int:nid>', methods=['GET'])
def detail(nid):
    # django获取session: request.session.get(key)
    # flask从session中拿出user
    user = session.get('user_info')
    if not user:
        return redirect('/login')
    info = USERS.get(nid)
    return render_template('detail.html', info=info)


@app.route('/index', methods=['GET'])
def index():
    user = session.get('user_info')
    if not user:
        url = url_for('l1')  # 反向解析
        return redirect(url)
    return render_template('index.html', user_dict=USERS)


@app.route('/login', methods=['GET', 'POST'], endpoint='l1')  # endpoint别名,用作反向解析,如果不写,就用视图函数名作为别名
def login():
    # django视图函数传入的是当次请求request
    # flask的request是导入进来的,是全局request,如何区分是哪个url的请求?
    if request.method == 'GET':
        return render_template('login.html')
    else:
        # post请求提交过来的数据放在form中
        # get请求提交过来的数据放在query_string中
        user = request.form.get('user')
        pwd = request.form.get('pwd')
        if user == 'zl' and pwd == '123':
            # django设置session: request.session[key] = value
            # flask的session是导入进来的,是全局session,如何区分用户?
            session['user_info'] = user
            return redirect('/index')
        return render_template('/login.html', error='用户名或密码错误')


if __name__ == '__main__':
    app.run()
login.html
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户登录</h1>
    <form action="" method="post">
        <input type="text" name="user">
        <input type="text" name="pwd">
        <input type="submit" value="登录">{{error}}
    </form>
</body>
</html>
index.html
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        <!--jinja2模板支持python语法,可以加括号调用方法-->
        <!--jinja2模板的字典支持多种方式取值,django模板语法只支持v.name-->
        {% for k, v in user_dict.items() %}
        <tr>
            <td>{{k}}</td>
            <td>{{v.name}}</td>
            <td>{{v['name']}}</td>
            <td>{{v.get('name')}}</td>
            <td><a href="/detail/{{k}}">查看详情</a></td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>
detail.html
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>详细信息 {{info.name}}</h1>
    <div>
        {{info.text}}
    </div>
</body>
</html>
posted @ 2022-10-05 23:25  不会钓鱼的猫  阅读(40)  评论(0编辑  收藏  举报