1. 程式人生 > 其它 >Flask + AngularJS + Jinja2 實現前後端互動

Flask + AngularJS + Jinja2 實現前後端互動

技術標籤:pythonangularjsflask

1.需求

  • 做一個網頁,需要一個由後端控制內容的選單。一開始的時候是所有內容都在jinja2模板中進行渲染。後面發現這樣每個檢視都需要傳選單的資料。就想著能不能寫一個介面,前端只要請求這個介面進行渲染就可以了,這樣就可以只在base模板中寫選單,後面的直接繼承即可。

2.框架選擇

  • 由上面的需要,一開始還不知道這麼寫前端,只知道用ajax請求選單的介面,能是能拿到資料。但是對於基板小白的筆者來說,怎樣將拿到的資料放在該放的位置就是問題了。

  • 好在前幾天在看Spring Could 框架的時候看到了一篇教程,講的是如何用AngularJS 消費RESTful web服務。看到裡面用的AngularJS 很簡單就實現了與Spring Could的互動。只要引入angularjs.js就能用了,其請求後端的$http

    也跟ajax的get方法差不多,最方便的是拿到資料後傳給$scope就可以嵌入到html的任何地方,就像jinja2。

  • 當然也有不足的地方。一是,AngularJS 的變數獲取字元和jinja2的衝突了,都是用的{{ }}。二是,在手機上好像不能用,目前還不知道是什麼原因。

3.設計開發

/BookStore/static/js/fronts/get_book_type.js

angular.module('demo', [])
.controller('Hello', function($scope, $http) {
    $http.get('http://127.0.0.1:5000/get_book_type'
). then(function(response) { $scope.types = response.data; console.log($scope.types) }); });
  • js檔案這裡就跟ajax差不多,用$http.get請求資料,然後儲存到$scope
<!doctype html>
<html ng-app="demo">
<head>
    <title>Hello AngularJS</title>
    <
script type="text/javascript" src="{{ url_for('static', filename='js/angular.min.js') }}"></script> <script type="text/javascript" src="{{ url_for('static', filename='js/fronts/get_book_type.js') }}"></script> </head> <body> <div ng-controller="Hello"> <ul> <li ng-repeat="type in types"><a href="/get_nav_data?book_type={{'{{type}}'}}">{{ '{{type}}' }}</a></li> </ul> </div> </body> </html>
  • html首先需要匯入angular.min.js檔案,這裡是在官網下載好了的,也可以用國內的cdn加速。還要匯入上面用來獲取後端資料的get_book_type.js檔案。
  • 然後就是設定angularjs的html標籤屬性。ng-app="demo"是作用域,ng-controller="Hello"直譯控制器(還沒看過教程),ng-repeat="type in types"這個是迴圈語句,我從後端傳來的是陣列,可以用迴圈取出來。

4.自測

  • 在前端列印後端傳來的資料,ok沒問題 在這裡插入圖片描述

  • 在專案外測試的結果ok
    在這裡插入圖片描述

  • 加入到專案中,將選單放到base.html模板中,結果也ok
    在這裡插入圖片描述
    在這裡插入圖片描述

5.後端Flask實現

@bp.route('/get_book_type')
def get_book_type():
    book_type_list = choice_book_type()
    # 解決跨域問題:https://blog.csdn.net/weixin_42902669/article/details/90728697
    resp = jsonify(book_type_list)
    resp.headers['Access-Control-Allow-Origin'] = '*'
    # resp.headers['"Access-Control-Allow-Methods"'] = '"PUT,POST,GET,DELETE,OPTIONS"'
    return resp
  • 遇到一個坑!No 'Access-Control-Allow-Origin' header is present on the requested resource.用AngularJS 請求Flask 資料的時候,會有跨域的問題出現。後面google了一下,分兩種解決方法,一種是在前端解決,在請求頭header中加什麼引數的樣子(沒試過)。另一種是在後端解決,配置Flask關閉跨域的配置項,以及寫一個裝飾器設定允許跨域的IP地址的請求。在這裡插入圖片描述

  • 看了幾篇解決方案,都不太行,要麼場景不符,要麼實現起來太複雜。這裡我就只有一個介面而已,沒必要搞的這麼複雜。

  • 好在後面找到了簡單又好用的方法。就是上面用的,在介面的response響應頭中新增Access-Control-Allow-Origin允許的的跨域請求就ok了。

6.總結

  1. 經過這個例子才發現Flask 的jsonify()返回的是一個reponse類物件<class 'flask.wrappers.Response'>,之前一直都只知道直接return jsonify()其功能是可以將python的資料型別轉為json並返回。現在想想,感覺傻了。檢視函式返回的是response響應體,那jsonify返回的不就是response了嘛!
  2. 是前後端分離開發會遇到請求跨域的問題。
  3. AngularJS用起來真香,不過在手機瀏覽器上AngularJS沒有成功渲染資料,有空的時候可以好好的深入瞭解一下。

完整的專案程式碼庫:https://github.com/caisi35/BookStore