WEB服务Flask第二天

WEB服务Flask第二天

一、路由、request与response

1. 1 路由规则

简单使用路由案例:

@blue.route('/find')
def find():
    return ""

请求的url是 http://localhost:5000/find。路由中配置的路径即是请求的path路径。

如果使用"蓝图"则在注册时,可以注明它的url前辍。

app.register_blueprint(bank.blue, url_prefix="/bank")

通过url_prefix参数指定某一个模块下的所有请求资源,对于/find路由来说的,应该是/bank的子路径(路由),访问全路径是 http://localhost:5000/bank/find。

1.1.1 路由的path中参数

语法:

@app.route('/find/<converter:word>', methods=['GET'])
def find(word):
    return ""

converter 是参数的转换器, 一般是指定的类型,如string, **int, float,path **,uuid, any。

其中any()表较特殊,可以指定任意的类型转换器, 如 <any(int, string, uuid): word>, 但目前最新flask版本不支持any()动作,直接写成"/find//". word表示任意类型。

另外,path转换器主要用于引用别的网址时使用。

@app.route('/forward/<path:url>')
def forward(url):
    # 重定向url
    return redirect(url)

以上的路由配置,对于"/forward/http://www.baidu.com" 路径是合法,如果将path转换器换成string有可能会出错。

另外,path路径中可以接收多个参数

@blue.route('/add/<bankName>/<int:page>')
def addCard(bankName, page):
    return "%s 开户成功! 在第 %s 页" % (bankName, page)
1.1.2 路由的请求方法

路由中的请求方法是通过methods设置的, 且要求是list类型。

@app.route('/find/<word>')
def forward(word):
    # keyword有可能是银行的id, 名称, 地址
    return "keyword 是str类型, 值是 %s" %( keyword)

上面的注册路由是没有指定methods, 默认中包含GET和OPTIONS。

常见的请求方法:

  • GET 查询数据使用, 可以上传的参数大小限于1M以内, 参数是显示在请求地址中的。
  • POST 添加或编辑数据时使用, 可以上传超过1G的大数据, 且以表单参数的方式上传,并不显示请求地址中, 相比于GET,请求参数比较安全且支持大数据或文件。
  • PUT 更新数据时使用, 局部数据的修改,如修改用户的口令或头像
  • PATCH 批量更新数据时使用, 整体的数据修改,如修改用户的收货地址、实名认证、绑定银行卡。
  • DELETE 删除数据操作时使用。
  • 其它的方法: OPTIONS、HEAD

如声明一个处理函数,用于删除银行信息,正确的路由配置如下:

@app.route('/del/<int:bank_id>', methods=["DELETE"])
def delete4id(bank_id):
    return "删除操作成功!"

针对PUT/DELETE/POST/GET等url接口测试,可以使用requests库

pip install requests

requests库中提供相关函数,函数的名称与请求方法是一一对应,当然也可以使用requests.request()方法是最全的方法,其它的函数都是在request()方法之上重新封装的。

url = "http://localhost:5000/bank/del/100"
method='DELETE'
resp = requests.request(method, url)
print(resp.text)

也可以使用请求方法对应的requests库的相关函数,如:

url = "http://localhost:5000/bank/del/100"
method='DELETE'
resp = requests.delete(url)
print(resp.text)
1.1.3 路由的反向解析
from flask import url_for
from flask import Blueprint

blue = Blueprint("cardBlue", __name__)

@blue.route('/add/<bankName>')
def add(bankName):
    ...
    
@blue.route('/select')
def select():
  	return "<a href=%s>进入下一个页面</a>"  % url_for('cardBlue.add', bankName="中国银行")

url_for(“函数名”, **kwargs) 反向解析获取flask的路由注册的路径

url_for(‘蓝图名.函数名’, **kwargs) 反向解析指定蓝图下的路由注册的路径

@blue.route('/add/<bankName>/<int:page>')
def addCard(bankName, page):
    return """
        %s 开户成功! 在第 %s 页
        <br>
        <a href="%s">返回首页</a>
    """ % (bankName, page, url_for('index'))
@app.route("/")
def index():
    return """
        <ul>
            <li> <a href="%s">银行卡开户</a></li>
            <li> <a href="%s">银行管理</a></li>
            <li> <a href="%s">用户管理</a></li>
        </ul>
    """ %(
        url_for('cardBlue.addCard', bankName="中国银行", page=3),
        url_for('bankBlue.edit', bankId=1),
        url_for('userBlue.find'),
    )

1.2 请求对象

from flask import request

请求对象本质上是封装客户端发送的请求数据,在Flask中由Werkzeug库(实现Python的WSGI接口)封装的, 包含请求的路径、请求的方法、请求的头、请求中包含的Cookie、请求的参数及上传的数据。

一个请求对象中包含数据的属性一般都是dict类型。如:

  • request.args 查询参数, url路径中使用?分隔的查询参数
  • request.form 表单参数, 一般是post请求方法中包含的数据
  • request.headers 请求头
  • request.cookies Cookie数据
  • request.files 上传的文件
  • request.method 请求方法, 且大写字母表示的
  • request.url 请求的路径(完整路径), 如http://localhost:5000/find?id=1&name=disen。
  • request.remote_addr 远程访问的客户端IP地址
<ul>
        <li>url: {{ request.url }}</li>
        <li>base_url: {{ request.base_url }}</li>
        <li>host_url: {{ request.host_url }}</li>
        <li>path: {{ request.path }}</li>
        <li>method: {{ request.method }}</li>
        <li>客户端IP: {{ request.remote_addr }}</li>
        <li>请求头: {{ request.headers }}</li>
        <li>Cookie: {{ request.cookies }}</li>
    </ul>
@blue.route('/find', methods=['GET'])
def find():
    print('url', request.url)
    print('base_url', request.base_url)
    print('host_url', request.host_url)
    print('path', request.path)
    print('headers', request.headers)
    print('cookie', request.cookies)

    return render_template("user_list.html", request=request)

1.3 响应对象response

在服务端,当业务处理完成后,生成响应的数据并封装成响应对象,并传给Python的WSGI, 由WSGI向客户端发送数据流。

  1. 直接返回文本和状态码

    flask的处理函数如果直接返回文本或附带一个响应的状态码,则会自动封装一个简单Response对象,且数据类型默认为: text/html;charset=utf-8

    @blue.route('/publish', methods=['POST'])
    def publish_bank():
        return '{"id": 101, "age": 20}', 200
    

    如果返回是一个html文本数据,可以使用render_template()函数,将写好的html模板经过渲染之后生成的html返回会更好些。

  2. 使用make_response(data, code) 生成response对象

    这种方式是较为常用的方式,通过生成的response响应对象,可以设置响应的header相关的信息。

    @blue.route('/publish', methods=['POST'])
    def publish_bank():
        data = '{"id": 101, "age": 20}'
        code = 200
    
        # 将数据和响应的状态码封装到response对象中
        response = make_response(data, code)
    
        # 根据数据的类型,设置响应头
        response.headers['Content-Type'] = 'application/json;charset=utf-8'
        
        return response
    
  3. jsonify()快速生成json响应对象

    此函数返回也是一个response对象,只不过response对象的headers已经设置了content-type属性为application/json。

    @blue.route('/publish', methods=['POST'])
    def publish_bank():
        data = '{"id": 101, "age": 20}'
        code = 200
        return jsonify(data, code)
    
  4. Response类生成响应对象

    @blue.route('/publish', methods=['POST'])
    def publish_bank():
        data = '{"id": 101, "age": 20}'
        code = 200
        # Response(response=None,status=None,
        #         headers=None, mimetype=None,content_type=None,
        #         direct_passthrough=False)
        response = Response(data, code, content_type="application/json")
        return response
    

    创建Response对象方法中,可以省略code, 同时也可以将content_type改为mimetype。mimetype表示文件的数据类型, 和content_type表示含义相同。

  5. 重定向

    在一个请求中,由于业务处理的要求,在处理业务之后,需要进入新的页面。而这个页面之前已声明它的路由,则需要使用重定向的方式进入到下一个页。

    【注意】重定向也是响应对象,必须要返回。而且相对于浏览器或客户端再次发送新的请求。

    @blue.route('/list')
    def listCard():
        return render_template('card/list.html')
    
    @blue.route('/add', methods=['GET', 'POST'])
    def addCard():
        if request.method == "POST":
            # 接收开户信息
            bankId = request.form.get('bank')
            username = request.form.get('username')
            phone = request.form.get('phone')
    
            # 验证数据是否为空
            # 假如操作成功
            # 进入列表页面中
            return redirect(url_for('bankBlue.listCard'))
    
        # GET请求,响应是开户页面
        return render_template('card/add.html')
    
    <h3>开户页面</h3>
    <form action="/bank/add" method="post">
        <select name="bank">
            <option value="0">--请选择银行--</option>
            <option value="1">中国银行</option>
            <option value="2">中国工商银行</option>
        </select>
        <br><input name="username" size="20" placeholder="用户名"></input>
        <br><input name="phone" size="20" placeholder="手机号"></input>
        <button>提交</button>
    </form>
    

1.4 请求异常处理

请求异常,在请求处理过程中,验证某一数据出现的错误,可以中断请求。如果请求异常不是请求数据而引起,或者说请求资源不存在或服务器发生异常,此时可以捕获异常。

1.4.1 abort()中断

在请求处理函数中,可以直接调用abort()函数,中断业务处理。

from flask import abort

@blue.route('/add', methods=['GET', 'POST'])
def addCard():
    if request.method == "POST":
        # 接收开户信息
        phone = request.form.get('phone')

        if phone == '17791692095':
            # 中断业务
            # abort(403)  # 发出一个异常响应码
            abort(Response("<h3 style='color:red'>%s 当前手机号不能被注册</h3>" % phone, 403))

    # GET请求,响应是开户页面
    return render_template('card/add.html')

abort()两种写法:

  • abort(status_code)
  • abort(Response(data, code, headers, …))

####1.4.2 捕获请求异常

通过相关的状态码,获取请求异常,并指定处理函数来响应异常的信息。

@app.errorhandler(404)  # 指定状态码捕获
def notfounded(error):
    print(error)
    return render_template('404.html')

建议处理异常的函数写在与app对象同一个脚本中。

如果处理业务中抛出相关的异常或发生500的异常,则可以指定异常类捕获

@blue.route('/list')
def listCard():
    raise Exception('抛出自己的业务异常')
    # abort(500)
    return render_template('card/list.html')
@app.errorhandler(Exception)
def handlerOfError(error):
    return render_template('500.html')

二、Cookie与Session技术

2.1 Cookie存储技术

Cookie数据存储技术,它的数据存储在客户端(浏览器),在浏览器中会为每个站点(host)创建存储Cookie的空间出来, Cookie的数据存储以Key=Value存储的,但是每个key都有生命周期(有效期)。一个完整的Cookie信息包含: 名称、内容、域名、路径(/)、有效时间(创建时间、到期时间),如查看chrome下localhost域名下的所有cookie数据: chrome://settings/siteData

在搜索Cookie的文本框中输入"localhost", 查出localhost站点之前创建的Cookie。

2.1.1 向客户端写入Cookie

使用response对象的set_cookie()方法可以向客户端添加Cookie:

# werkzeug.wrappers.base_response.BaseResponse
def set_cookie(
        self,
        key,
        value="",
        max_age=None,
        expires=None,
        path="/",
        domain=None,
        secure=False,
        httponly=False,
        samesite=None,
    ):pass
2.1.2 将客户端的Cookie删除

使用响应对象的delete_cookie()方法

 def delete_cookie(self, key, path="/", domain=None):

三、模板技术与静态资源

##四、文件上传

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值