Flask轻量级Python的Web框架

1.概念介绍

       WSGI 全称Web Server Gateway Interface,web服务器网关接口,实际上就是一种协议,我们的应用(Django,Flask)实现了WSGI。

       Werkzeug服务:实现wsgi协议的模块,本质是socket服务端,用于接收http请求并对请求进行预处理,然后触发Flask框架。

       jinja2模板:可以对响应数据做模板化处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。也就是说,也可以不处理。

       Flask框架:一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,flask依赖wsgi

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

2.安装

       pip install flask

3.基本使用

0>示例

from flask import Flask
app = Flask(__name__)
 
@app.route('/')
def hello_world():
    return 'Hello World!'
 
if __name__ == '__main__':
    app.run(debug=True)

 debug=True:表示代码有修改后,服务自动重启

__name__:是一个变量。前后加了爽下划线是因为是因为这是系统定义的名字。普通变量不要使用此方式命名变量。标识模块                      的名字的一个系统变量。这里分两种情况:假如当前模块是主模块(也就是调用其他模块的模块),那么此模块名                        字就是__main__,通过if判断这样就可以执行“__mian__:”后面的主函数内容;假如此模块是被import的,则此模块                        名字为文件名字(不加后面的.py),通过if判断这样就会跳过“__mian__:”后面的内容。

import :是要执行所import的模块的

设置json编码格式:如果为False 就不使用ascii编码:app.config['JSON_AS_ASCII']=False 

设置响应头信息Content-Type:app.config['JSONIFY_MIMETYPE'] ="application/json;charset=utf-8"  (注意 ;charset=utf-8)

1> 实例化Flask对象时,可选参数的使用说明

         实例化一个Flask对象,这是基本的写法:

         app=Flask(__name__)

         但是它还有很多的可选参数

        Flask(

                  import_name,              

#__name__

                  static_url_path,               

#静态文件的地址前缀,写成什么,访问静态文件时,就要在前面加上这个,例如:app = Flask(__name__,template_folder='templates',static_url_path='/xxxxxx')

                  template_folder,

#模板所在文件夹的名字

                  instance_path,              

#用来找配置文件的,指定from_pyfile查询文件的路径,不设置时,默认寻找和app.run()的执行文件同级目录下的instance文件夹;如果配置了instance_path(注意需要是绝对路径),就会从指定的地址下里面的文件

                  instance_relative_config,              

#用来找配置文件的,默认为False,当设置为True时from_pyfile会从instance_path指定的地址下查找文件。

                  root_path              

#可以不用填,会自动找到,当前执行文件,所在目录地址

          )

绑定路由的两种方式

       本质是将url和视图函数封装成一个Rule对象,添加到Flask的url_map字段中

方式一:最简单的方式

 

from flask import Flask
app=Flask(__name__)

@app.route('/test1',methods=['GET'])
def hello_world():
    return 'hello world1=====11111'

if __name__ == '__main__':
    app.config['JSONIFY_MIMETYPE']="application/json;charset=utf-8" 
    app.run(debug=True)

方式二:通过app.add_url_rule()调用路由

from flask import Flask
app=Flask(__name__)

def hello_world2():
    return 'hello world2=====22222'

app.add_url_rule(rule='/test2',view_func=hello_world2, methods=["GET"])

if __name__ == '__main__':
    app.config['JSONIFY_MIMETYPE']="application/json;charset=utf-8" 
    app.run(debug=True)

其他特别的方式:

@app.route('/<name>')  #设置url传参数 http://127.0.0.1:5000/zhanggen
def first_flask(name):
@app.route('/<int:age>/')  #设置url传参数 http://127.0.0.1:5000/18/
def first_flask(age):
@app.route('/<float:salary>/')  #设置url传参数http://127.0.0.1:5000/2345555.8889/
def first_flask(salary):
@app.route('/<path:url>/')  #设置url传参数:http://127.0.0.1:5000/http://www.baiu.com/
def first_flask(url): 

参数含义:

@app.route和app.add_url_rule参数:
            rule,                       URL规则
            view_func,                  视图函数名称
            defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
            endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
            methods=None,               允许的请求方式,如:["GET","POST"]
            

            strict_slashes=None,        对URL最后的 / 符号是否严格要求,
                                        如:
                                            @app.route('/index',strict_slashes=False), #当为False时,url上加不加斜杠都行
                                                访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可
                                            @app.route('/index',strict_slashes=True)  #当为True时,url后面必须不加斜杠
                                                仅访问 http://www.xx.com/index 
            redirect_to=None,           由原地址直接重定向到指定地址,原url有参数时,跳转到的新url也得传参,注意:新url中不用指定参数类型,直接用旧的参数的类型
                                        如:
                                            @app.route('/index/<int:nid>', redirect_to='/home/<nid>') # 访问index时,会直接自动跳转到home,执行home的函数,
                                                            不执行index的
                                            
                          或
                                            def func(adapter, nid):
                                                return "/home/888"
                                            @app.route('/index/<int:nid>', redirect_to=func)

2>装饰器

概念:

       装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

      概括的讲,装饰器的作用就是为已经存在的函数或对象添加额外的功能

#给Flask视图加装饰器
#1、定义1个装饰器

def auth(func):
    print('我在上面')
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner


app=Flask(__name__)

@app.route('/',methods=['GET'])
@auth #注意如果要给视图函数加装饰器,一点要加在路由装饰器下面,才会被路由装饰器装饰
def first_flask():
    print('ffff')
    return 'Hello World'

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

其中*args:可变参数的用法,允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple(元组)

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

#聪明方法,可以在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去
>>> nums = [1, 2, 3]
>>> calc(*nums)
14

其中**kwargs:关键字参数用法,允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict(字典)

def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

之所以要加*args,**kwargs,是因为函数有千千万,你只管你自己的函数,别人的函数参数是什么样子,鬼知道?还好Python提供了可变参数*args和关键字参数**kwargs,有了这两个参数,装饰器就可以用于任意目标函数了。

3>请求

request.method: 获取请求方法

request.json

request.json.get("json_key"):获取json数据 **较常用      

request.args.get('name') :获取get请求参数   

request.form.get('name') :获取POST请求参数

request.url:获取访问url地址,例如http://127.0.0.1:5000/?age=18;

request.base_url:获取访问url地址,例如 http://127.0.0.1:5000/;

4>响应

return "字符串" :响应字符串

return render_template('html模板路径',**{}):响应模板,例如:

render_template("login.html",msg="用户名或者密码错误")

return redirect('/index.html'):跳转页面或者路径

路径:redirect("/index")

响应json格式

方式1: return jsonify(user_list) 

app.config['JSON_AS_ASCII']=False #指定json编码格式 如果为False 就不使用ascii编码,

app.config['JSONIFY_MIMETYPE'] ="application/json;charset=utf-8" #指定浏览器渲染的文件类型,和解码格式;

方式2:

return Response(data,mimetype="application/json;charset=utf-8",)

5>flask的cbv视图

CBV(class base views) 就是在视图里使用类处理请求。

Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:

  1. 提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
  2. 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

def auth(func):
    def inner(*args, **kwargs):
        result = func(*args, **kwargs)
        return result
    return inner

class IndexView(views.MethodView):
    # methods = ['POST']  #只允许POST请求访问
    decorators = [auth,]  # 如果想给所有的get,post请求加装饰器,就可以这样来写,也可以单个指定

    def get(self):   #如果是get请求需要执行的代码
        v = url_for('index')
        print(v)
        return "GET"

    def post(self):  #如果是post请求执行的代码
        return "POST"

app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  #name即FBV中的endpoint,指别名

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

6>Jinja2模板

Flask使用的是Jinja2模板,这里不感兴趣,就没有学习

7>Session

       除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥

  • 设置:session['username'] = 'xxx'
  • 删除:session.pop('username', None)

#coding=utf-8
from flask import Flask,render_template,request,redirect,session
import json
app = Flask(__name__)
app.secret_key = "sdsfdsgdfgdfgfh"   # 设置session时,必须要加盐,否则报错

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"],strict_slashes=False)  # 指定该路由可接收的请求方式,默认为GET
def login():
    if request.method=="POST":
        return 'post method is not support'
    else:
        username = request.args.get("username")
        password = request.args.get("password")
        if username=="ssj" and password=="123":
            session["user_info"] = username
            # session.pop("user_info")  #删除session
            return redirect("/index")
        else:
            # return render_template("login.html",**{"msg":"用户名或密码错误"})
            return json.dumps({'msg':'用户名或者密码错误'})

@app.route("/index",methods=["GET","POST"],strict_slashes=False)
@wrapper    #自己定义装饰器时,必须放在路由的装饰器下面
def index():
    # if not session.get("user_info"):
    #     return redirect("/login")
    username=session.get("user_info")
    return 'index.html is ok,'+username


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

  • Django中,session保存在服务端的数据库中,数据库中保存请求用户的所有数据,服务端数据中{'随机字符串':加密后的客户相关信息},请求完成后,把随机字符串作为值,返回给客户端,保存在客户端的cookie中,键为:sessionid,值为:服务端返回的随机字符串;即{'sessionid':'随机字符串'}
  • Flask中,服务端什么都不存,用户第一次请求时,在内存中生成一个空字典,将这个空字典加密后,返回给客户端,保存在客户端的cookie中,键为’session',值为:加密后的字典,下次访问时,读取客户端cookie中key为session对应的值,然后进行解密(如果不能按之前的的加密方式对应个解密方式解密,即认为第一次请求,重新生成空字典),解密成功后,可以对字典进行操作,保存新数据在字典中,请求完成后,会重新加密这个字典,返回个客户端保存

8>flash 闪现

message是一个基于Session实现的用于保存数据的集合,其特点是:一次性。不长期占用内存。

session存在在服务端的一个字典里面,session保存起来,取一次里面还是有的,直到你删除之后才没有了

本质

flash是基于session创建的,flash支持往里边放值,只要你取一下就没有了,相当于pop了一下。不仅可以拿到值,而且可以把其从session里的去掉,

基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。

from flask import  flash,get_flashed_messages
flash({'user_info':username}) #添加

username=get_flashed_messages()#获取并删除
print(username)

9>中间件

在函数执行之前或函数执行之后想做点事情,有2种方式

第一种:装饰器

第二种:flask里面的扩展,相当于django中的中间件

flask也有中间件功能和Django类似,不同的是使用的是使用3个装饰器来实现的;

1.@app.before_first_request :请求第1次到来执行1次,之后都不执行;

2.@app.before_request:请求到达视图之前执行;(改函数不能有返回值,否则直接在当前返回)

3.@app.after_request:请求 经过视图之后执行;(最下面的先执行)

 

未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彼岸花@开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值