從零開始用 Flask 搭建一個網站(二) 介紹了有關於數據庫的運用,接下來咱們在完善一下數據在前端以及前端到後端之間的交互。本節涉及到前端,所以也會講解一下 jinja2 模板、 jQuery 、 ajax 等用法。javascript
下面咱們來建立兩個界面,一個能夠新建 channel ,並顯示,另外一個能夠建立 integration ,而且能夠綁定一個以前建立的 channel 。css
post2channel.htmlhtml
{% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% block head %} {{ super() }} <link rel="stylesheet" href="{{ url_for('static', filename='css/post2channel.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='css/toastr.css') }}"> <script type="text/javascript" src="{{ url_for('static', filename= 'js/jquery.min.js') }}"></script> <script type="text/javascript" src="{{ url_for('static', filename='js/toastr.js') }}"></script> <script type="text/javascript" src="{{ url_for ('static', filename='js/')}}"></script> {% endblock %} {% block title %}極光寶盒-建立集成{% endblock %} {% block navbar %} <div id="navigationbar"></div> {{ super() }} {% endblock %} ...
咱們從第一行開始來說解一下這個模板,第一句前端
{% extends "base.html" %}
從字面上能夠明白這個模板繼承了 base.html 模板,使用 {% %} 是 jinja2 模板的語法,表示語句塊,還有一種分隔符 {{ }} ,表示變量,一般用來在模板上顯示。接下來是java
{% block head %}
能夠看到也是比較容易理解的語法, block 後接一個 block name ,表示一個塊開始的聲明,結束的時候用 {% end %} 便可。在塊中可使用普通的 HTML 語法。{{ super() }} 表示繼承父模板的塊聲明,這裏指繼承 base.html 中聲明的 head 塊。接下來是 css 和 js 文件的引用。此頁面使用了 toastr 來顯示通知,相似於 Android 中的 Toast ,有興趣的能夠了解一下它的詳細用法。jquery
接下來是 HTML 代碼,有一個下拉輸入框和按鈕。git
<ul id="content" class="dropdown-menu dropdown-menu-right"> {% for channel in channels %} <li id="{{ channel }}" class="channel_class"><a>{{ channel }}</a></li> {% endfor %} </ul>
以上代碼就是下拉輸入框中的數據來源,用了一個 for 循環來遍歷 channels 列表,而且用 li 包裹每一個元素,這也是模板常見的用法。 channels 是在視圖函數中傳過來的。github
auth/views.pyajax
@auth.route('/new/post_to_channel', methods=['GET']) def post_to_channel(): developer = get_developer() dev_key = developer.dev_key channels = get_channel_list() return render_template('auth/new/post2channel.html', **locals())
remder_template 的第二個參數代表,渲染這個 post2channel.html 頁面的時候,把以上全部的變量都傳遞到頁面中,這樣就可使用 {{ }} 模板語法拿到。接下來回到 post2channel.html , 看到<script></script>部分:數據庫
$('#create_integration_btn').click(function () { var channel = $('#selected_channel').val(); console.log('create integration, channel: ' + channel); if (channel != '') { $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", url: "../../v1/developers/{{ dev_key }}/integrations", data: JSON.stringify({channel: channel}), success: function (data) { if (data != undefined) { if (data["token"]) { window.location.href = '/auth/manage/create_integration/' + data["integration_id"] + '/' + data["token"] + '/' + channel } } else { toastr.error("服務器異常"); } }, error: function (error) { console.log(error); toastr.error("建立失敗"); }, dataType: "json" }) } })
這是建立集成按鈕的邏輯,用 jQuery 的 ajax 發送 post 請求,以 json 格式將輸入框中的 channel 值傳到 url 代表的視圖函數。這裏的 url 是相對路徑。在 ajax 中有 success 和 error 兩個函數,分別是請求成功和失敗的回調函數。下面看到這個請求的視圖函數,咱們來看看視圖函數是如何處理從頁面傳過來的數據。
api_1_0/developers.py
# 添加一個集成,並返回 integration_id ,若是 channel 已存在,直接綁定該 channel , 不然新建一個 channel@api.route('/developers/<dev_key>/integrations', methods=['POST']) def create_integrations(dev_key): # 先判斷一下傳過來的 json 數據是否符合要求 if not request.json or not 'channel' in request.json: print("request json error") abort(400) #從數據庫獲得 developer developer = Developer.query.filter_by(dev_key=dev_key).first() if developer is None: print("developer not found") abort(400) #如下省略 ... #最後返回相關數據 return jsonify({'integration_id': new_integration_id, 'token': token.decode('utf-8')}), 201
以上代碼建立成功後也返回了一個 json ,這樣在 success 的回調函數中就能獲得這個數據,用於在跳轉到其餘界面的時候作一些初始化操做。即如下代碼:
if (data != undefined) { if (data["token"]) { window.location.href = '/auth/manage/create_integration/' + data["integration_id"] + '/' + data["token"] + '/' + channel } }
這裏將參數放到 url 中,調用了對應的視圖函數:
auth/views.py
@auth.route('/manage/create_integration/<string:integration_id>/<string:token>/<string:channel>', methods=['GET', 'POST']) def create_integration(integration_id, token, channel): integration = Integration.query.filter_by(integration_id=integration_id).first() channels = get_channel_list() developer = get_developer() dev_key = developer.dev_key return render_template('auth/create.html', **locals())
能夠看到上面的參數就是從 post2channel 頁面傳過來的,而且還從數據庫中查詢到對應的 integration ,而後將相關數據傳到 create.html ,讓後者渲染頁面。
咱們經過一個例子看到數據在前端和後端、前端之間的交互。總結一下,無非就是在前端頁面中發送請求,而後在視圖函數中操做數據庫,而且返回相關數據,回調到前端頁面中,最後在回調中調用另外一個視圖函數,在跳轉頁面時利用獲得的數據渲染頁面。一切就是這麼簡單,沒什麼黑魔法!源碼在 github 上。下一節介紹一下 flask_oauthlib 的用法,學習一下如何使用 oath2 第三方受權登陸以及調用提供方的相關 API 。
做者: KenChoi - 極光( JPush 爲極光團隊帳號,歡迎關注)
原文:從零開始用 Flask 搭建一個網站(三)
知乎專欄:極光日報