2014-02-14 46 views
0

假設我想使用Flask與我從數據庫中獲取的某些特定數據來呈現頁面(不僅僅是JSON)。例如如何從沒有AJAX的Flask中返回JSON數據

display_data.html包括:

<script src='display_data.js'></script> 
... 
<h1>Data display page!</h1> 
<div id="chartContainer"></div> 

display_data.js

$(function() { 
    draw_chart($("#chartContainer"), json_data); 
    //draw_chart is defined elsewhere and json_data is what I want to pass in 
}); 

的Python:

@app.route('/<data_id>') 
def get_display_data_page(data_id): 
    data = get_data_by_id(data_id) 
    return render_template('display_data.html', data = data) 

我想,如果我想只是 「渲染模板」,我會必須包括display_data.html以下的其他地方:

<script>window.json_data = {{ data | tojson | safe}}</script> 

這種模式味道不好:我要離開一個對象的全局命名空間(這樣我的JS文件都可以訪問它),顯示數據爲純文本,並呈現在一個字符串被解析成JSON所以JS可以使用它。看起來不好,但這確實奏效。其他

兩個選項:

  1. 返回與AJAX的數據。鑑於這篇文章的標題,我特別試圖避免ajax。其原因主要是我正在構建一個移動網站,並希望減少回到服務器的ping數量。我也在考慮封裝頁面(也許更形而上):一旦你擁有了它,你就擁有了全部。

  2. 通過Flask和Jinja呈現我的JS文件。這似乎是一個無賴,因爲我不得不寫下一條路線,並根據我在get_display_data_page中的相同邏輯渲染JS:通過其ID等查找數據。代碼複製和動態JS聲音像大不,不是我的。

有沒有一個已知的模式來做到這一點呢?

回答

1

如果您不想將數據保留在全局範圍內,則不需要。在模板中,你可以做這樣的事情:

<script> 
function registerTask(f, args) { 
    $(function() { 
    f.call(this, args); 
    }); 
} 

{% for name, args in js_tasks %} 
    registerTask({{name}}, {{ args | tojson | safe }}); 
{% endfor %} 
</script> 

然後,在你的JS文件,重新定義draw_chart只取數據(或周圍有一個包裝,你爲你的任務註冊表名稱中使用):

function draw_chart_task(data) { 
    draw_chart($('#chartContainer'), data); 
} 

最後,在你的控制器,只需提供數據和任務名稱爲一個元組:

return render_template('display_data.html', js_tasks=[('draw_chart_task', data)]) 

這可以確保你的JavaScript不只是採摘它的依賴出來全球範圍內,並且您不會額外撥打網絡電話。

數據在頁面的原始文本輸出中可見,但如果您也進行AJAX調用,則數據可見,您只需查看瀏覽器開發人員工具的其他面板即可看到它。