天天看點

在Flask架構将其做為後端服務,使用jQuery的AJAX進行互動的實戰在Flask裡的jQuery使用AJAX

在Flask裡的jQuery使用AJAX

JQuery是一個小型JavaScript庫,通常用于簡化DOM和JavaScript的使用。它是一個非常好的工具,可以通過在伺服器和用戶端之間交換JSON使網絡應用程式更加動态。

JSON是一種非常輕量級的傳輸格式,非常類似于Python原語(數字、字元串、字典和清單)。JSON受到廣泛支援,并且易于解析。幾年前,JSON開始流行,并在網絡應用程式中迅速取代了XML。

加載jQuery

<script type=text/javascript src="{{
  url_for('static', filename='jquery.js') }}"></script>
           

為了使用jQuery,必須首先下載下傳它,将其放在應用程式的靜态目錄中,并確定它已加載。理想情況下,你有一個所有頁面的布局模闆。在模闆的<body>底部添加腳本語句以加載jQuery:

使用 Google 的 AJAX 庫 API來載入 jQuery:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="{{
  url_for('static', filename='jquery.js') }}">\x3C/script>')</script>
           

一個簡單的方法是向頁面添加一個腳本标記,并設定一個全局變量來表示應用程式的根路徑。例子:

<script type=text/javascript>
  $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script>
           

在HTML中,script标記用于聲明CDATA,也就是說,聲明的内容将不會被解析。<the contents between script>and</script>将被視為腳本。這也意味着腳本标記之間沒有</。這裡|tojson将正确處理問題并轉義斜杠({{“</script>”|tojson|safe}}将呈現為“</sscript>”)。

在Flask 0.10中,我們更進一步,用unicode轉義了所有HTML标記,以便Flask可以自動将HTML轉換為安全标記。

JSON 視圖函數

現在,讓我們建立一個伺服器函數,它接受兩個URL參數(兩個要添加的數字),并向應用程式傳回一個JSON對象。下面的示例非常不切實際,因為類似的工作通常在用戶端完成,但它可以簡單而清晰地顯示如何使用jQuery和Flask:

from flask import Flask, jsonify, render_template, request
app = Flask(__name__)

@app.route('/_add_numbers')
def add_numbers():
    a = request.args.get('a', 0, type=int)
    b = request.args.get('b', 0, type=int)
    return jsonify(result=a + b)

@app.route('/')
def index():
    return render_template('index.html')
           

所見,我還添加了一個索引方法來呈現模闆。該模闆将如上所述加載jQuery。該模闆包含一個用于添加兩個數字的表單和一個觸發伺服器功能的連結。

注意,我們在這裡使用get()方法。它不會不打電話。如果字典的鍵不存在,将傳回預設值(此處為0)。此外,它會将值轉換為指定的格式(在本例中為int)。在腳本(API、JavaScript等)觸發的代碼中使用它特别友善,因為在這種情況下不需要特殊的錯誤報告。

手動推送情境

如果嘗試通路請求或在請求上下文之外使用它的任何内容,将收到以下錯誤消息:

RuntimeError:在請求上下文之外工作。

這通常意味着需要一個活動的HTTP請求來嘗試使用該函數。

有關如何避免此問題的資訊,請參閱測試文檔

這通常僅在測試代碼需要活動請求時發生。一種選擇是使用測試客戶機模拟完整的請求。

或者,可以在

with block_request_Context()

中使用test,塊中運作的所有内容都可以通路請求并填寫測試資料

def generate_report(year):
    format = request.args.get('format')
    ...

with app.test_request_context(
        '/make_report/2017', data={'format': 'short'}):
    generate_report()
           

拆解回調

拆除回調與請求分派無關,但在出現情況時由情況調用。即使在排程過程中存在未處理的異常和手動推送場景,也會調用這些函數。這意味着不能保證請求排程的任何其他部分會首先運作。確定這些函數的編寫方式不依賴于其他回調,并且不會失敗。

在測試期間,延遲請求的結束和彈出場景非常有用,以便可以在測試功能中通路其資料。使用withblock_Client()中的test儲存情況,直到with塊結束。

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello():
    print('during view')
    return 'Hello, World!'

@app.teardown_request
def show_teardown(exception):
    print('after with block')

with app.test_request_context():
    print('during with block')

# teardown functions are called after the context with block exits

with app.test_client() as client:
    client.get('/')
    # the contexts are not popped even though the request ended
    print(request.path)
           

關于代理的說明

Flask提供的一些對象是其他對象的代理。每個工作線程都可以以相同的方式通路代理,但每個工作線程在背景都綁定了一個唯一的對象。

在大多數情況下,你不必關心這個。然而,也有例外。在以下情況下,了解對象是代理對象是有益的:

代理對象不能将其類型僞裝為實際的對象類型。如果要執行執行個體檢查,必須檢查代理的原始對象。

對象引用非常重要,例如向背景線程發送信号或傳遞資料。

如果需要通路代理的源對象,請使用_get_ current_ object()方法:

app = current_app._get_current_object()
my_signal.send(app)
           

使用調試器

Flask提供了一個現成的調試器(請參閱調試模式),用于更深入的錯誤挖掘和跟蹤代碼執行。如果您需要使用其他Python調試器,請注意調試器之間的幹擾。在使用自己的調試器之前,請進行一些參數調整:

  • Debug—是否啟用調試模式并捕獲異常
  • use_Debugger—是否使用Flask内置調試器
  • use_Reload—子產品更改後是否重載和派生程序
  • Debug必須設定為true(即必須捕獲異常),另外兩個是任意的。

    如果使用Aptana或Eclipse進行故障排除,則use_Debugger和use_Reloaders必須設定為False。一種有用的配置模式如下(當然,縮進應該根據您的應用進行調整):

FLASK:
    DEBUG: True
    DEBUG_WITH_APTANA: True
           
if __name__ == "__main__":
    # To allow aptana to receive errors, set use_debugger=False
    app = create_app(config="config.yaml")

    use_debugger = app.debug and not(app.config.get('DEBUG_WITH_APTANA'))
    app.run(use_debugger=use_debugger, debug=app.debug,
            use_reloader=use_debugger, host='0.0.0.0')
           

注冊過濾器

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter
           
{% for x in mylist | reverse %}
{% endfor %}