Flask(請求和響應 五)

路由設計

前後端不分離,模版渲染

建議:一個視圖函數寫一個url

  1. 獲取所有的項目:/projects def list_projects()

  2. 獲取單個項目內容:/project/ def get_project()

  3. 修改某個項目內容:/project_edit/ def edit_project()

前後端分離,通過method

/project 類的視圖

  • GET 獲取單個資源 /project/

  • GET獲取全部/projects

  • PUT:修改資源

  • POST:創建資源

  • DELETE:刪除資源

一個簡單的ajax例子

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<p onclick="send_ajax()">點擊發送</p>
<script>
    function send_ajax() {
        $.ajax({
            url: "http://127.0.0.1:5000",
            data: JSON.stringify({username: "zhongxin"}),
            dataType: 'json',
            type: "POST",
            contentType: 'application/json',
            success: function (data) {
                alert('成功')
            }
        })
    }
</script>
</body>
</html>

python

from flask import Flask, request, render_template

app = Flask(__name__)


@app.route('/',methods=['GET','POST'])
def index():
    if request.method == 'GET':
        return render_template('index.html')
    elif request.method == 'POST':
        print(request.json)
        return '成功'


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

使用ajax會返回X-Requested-With: XMLHttpRequest可以在XHR中找到

XHR

request

from flask import request

request中包含了全部的請求信息和環境信息

request

values

  • form

  • args

cookies

請求的cookies,dict類型

data

包含了請求數據,並轉換成字符串,無法處理的mimetype則會轉換成stream

stream

如果請求的表單無法解碼,則會無改動的保存到這裏。

當請求數據轉換string時,使用data是最好的方式,這個stream只返回數據一次

headers

請求頭,dict類型

files

通過POST或者PUT請求上傳的文件

environ

WSGI隱含的環境配置

method

請求方式

remote_addr

遠程IP

user-agent

提供反扒和惡意攻擊

文件上傳

增加文件類型限制,文件大小限制

import os
from flask import Flask, request, render_template, send_from_directory

app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 10  # 最大上傳文件大小


@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        return render_template('index.html')
    elif request.method == 'POST':
        print(request.json)
        return '成功'


def allowed_format(filename):
    if os.path.splitext(filename)[-1].lower() not in ['jpg', 'png']:
        return False
    else:
        return True


@app.route('/upload', methods=['GET', 'POST'])
def upload():
    file = request.files.get('pic')
    if file is None:
        return render_template('index.html')
    if allowed_format(file.filename):
        file.save(file.filename)
        return '保存成功'
    return '保存失敗'


@app.route('/upload/<filename>')
def get_upload(filename):
    return send_from_directory(os.getcwd(), filename)


if __name__ == '__main__':
    app.run()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<p onclick="send_ajax()">點擊發送</p>
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="pic">
    <input type="submit">
</form>
<script>
    function send_ajax() {
        $.ajax({
            url: "http://127.0.0.1:5000",
            data: JSON.stringify({username: "zhongxin"}),
            dataType: 'json',
            type: "POST",
            contentType: 'application/json',
            success: function (data) {
                alert('成功')
            }
        })
    }
</script>
</body>
</html>


如果文件中存在空格,則可能出現問題

保存的時候需要添加secure_filename

from werkzeug.utils import secure_filename
file.save(secure_filename(file.filename))

響應頭

爲了返回一個json格式的內容,需要構造一個響應頭信息

方式一

import json

from flask import Flask

app = Flask(__name__)


@app.route('/')
def index():
    # 構造一個響應頭信息
    return json.dumps({"username": "zhongxin"}), 201, {"content-type": "application/json"}


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

方式二

import json

from flask import Flask, make_response

app = Flask(__name__)


@app.route('/')
def index():
    r = make_response(json.dumps({"username": "zhongxin1"}), {"content-type": "application/json"})
    return r


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

查看make_response的源碼:

def make_response(*args):
    if not args:
        return current_app.response_class()
    if len(args) == 1:
        args = args[0]
    return current_app.make_response(args)

當沒有入參的時候進入current_app.response_class()

進入之後可以看到response_class = Response

class Response(ResponseBase, JSONMixin):
    default_mimetype = "text/html"

    def _get_data_for_json(self, cache):
        return self.get_data()

    @property
    def max_cookie_size(self):
        if current_app:
            return current_app.config["MAX_COOKIE_SIZE"]
        return super(Response, self).max_cookie_size

所以默認的響應頭就是"text/html"

方式三

from flask import Flask, jsonify

app = Flask(__name__)


@app.route('/')
def index():
    r = jsonify({"username": "zhongxin2"})
    return r


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

可以看一下jsonify源碼,其實也就是用的make_response中的 current_app.response_class

def jsonify(*args, **kwargs):
    indent = None
    separators = (",", ":")

    if current_app.config["JSONIFY_PRETTYPRINT_REGULAR"] or current_app.debug:
        indent = 2
        separators = (", ", ": ")

    if args and kwargs:
        raise TypeError("jsonify() behavior undefined when passed both args and kwargs")
    elif len(args) == 1:  # single args are passed directly to dumps()
        data = args[0]
    else:
        data = args or kwargs

    return current_app.response_class(
        dumps(data, indent=indent, separators=separators) + "\n",
        mimetype=current_app.config["JSONIFY_MIMETYPE"],
    )
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章