1. 程式人生 > >Python框架學習之Flask中的Jinja2模板

Python框架學習之Flask中的Jinja2模板

代碼復用 表單 filter 中繼 IT AD 存在 開啟 技術分享

  前面也提到過在Flask中最核心的兩個組件是Werkzeug和Jinja2模板。其中Werkzeug在前一節已經詳細說明了。現在這一節主要是來談談Jinja2模板。

一、為什麽需要引入模板:

  在進行軟件開發的時候,我們都希望開發的軟件能夠有很低的耦合度。而在視圖中主要是處理業務邏輯和返回響應的,在web開發中,響應主要是渲染HTML文本,如果把渲染的這一個過程在視圖中做的話,會導致視圖特別擁堵,維護起來特別麻煩。這樣就引入了模板,目的是為了把視圖中的業務處理和響應分開,這樣維護的成本就會降低。

二、Jinja2模板引擎

  1. 什麽是模板?

    模板其實是一個包含響應的文件,只不過其中使用了很多變量來作為占位符,這些變量的值是通過視圖傳入的。

  Jinja2是一個模板引擎,使用Python實現的。起源於Django中的模板,然後又擴充了一些額外的功能。

  在Flask中使用render_template來使用某個模板文件,模板中的變量通過字典的方式傳入。

  2. 語法規則:

    {{ 變量 }}:直接在瀏覽器中輸出變量值

    {% if 條件%}.....{%elif 條件 %}.......{% endif %}:用來控制輸入

    {%for item in 序列 %} {% endfor %}:表示一個循環,其內部有一些特殊的變量:

      loop.index:表示下標從1開始,

      loop.index0:表示下標從0開始,

      loop.length:表示序列中元素的個數

  3.過濾器:

    過濾器的本質就是一個函數,但是不能定義在模板中,而是定義在.py文件中。

    作用:對輸出的變量做一些處理,如格式化。

    使用方式:{{ 變量 | 過濾器1 | 過濾器2 | 過濾器3 | ....}}

    常用內置過濾器: upper、lower、capitalize、safe等。

    重點說一下safe過濾器。從字面意思看,也知道這個過濾器是起到安全的作用。因為Jinja2模板默認是開啟轉義的。也就是說一些特殊的字符在渲染的時候,會屏蔽其特殊功能,這樣輸出的字符串瀏覽器就會把它當做是一般的字符串,不會對它進行翻譯,這樣通過JS也無法修改其樣式或其內容了。使用safe的話,一些特殊的字符就有特殊的作用,瀏覽器就會將其翻譯過來!比如當視圖往模板中傳入"<h1>Index</h1>",如果沒有使用safe過濾器的話,展示在瀏覽器的效果就是"<h1>index</h1>";但如果使用了safe過濾器的話,展示的結果就是變成一級標題!

    技術分享圖片

    自定義過濾器:除了使用Flask內置的過濾器外,我們還可以自定義一些過濾器。

 1 # 自定義過濾器
 2 def my_filter(name):
 3     return name.upper()
 4 
 5 # 把過濾器添加到系統的過濾器中
 6 app.add_template_filter(my_filter, myfilter1)
 7 
 8 
 9 # 過濾器實現形式二,使用裝飾器
10 @app.template_filter(myfilter2)
11 def my_filter2(str):
12     return str.capitalize()

四、模板代碼復用

  1. 為什麽需要模板代碼復用?

   一個網頁一般是有頭部、中間體和尾部三個部分。同一個網站中可能有很多個頁面,但是頭部和尾部頁面的重合度特別高,這部分的代碼我們可以通過其他方式給獲取過來,而不是再繼續寫。這樣我們只需要實現中間部分的網頁就可以了。這裏電商網頁為例。

  技術分享圖片

   

  2. 代碼復用的方式:

  (1). 繼承:{ % block xxx%} { % endblock xxx%}

    在子模板中使用{% extends ‘base.html‘ %} 把父模板中的數據繼承過來,這條語句一般寫在子模板中的第一行;

    使用這種方式就相當於在父模板中,挖很多坑,然後在子模板中通過使用{% block content %}{% endblock content%}來重寫中間體的內容,實現自定義功能;

    除了把父模板中的某段數據給改寫了之外,還可以使用{{ super() }}來調用父模板中某段數據。

  (2). 宏: {% macro fun_name(arg1, arg2,....) %} 某個功能 {% endmacro %}

    宏的本質上是一個函數,定義在模板當中。

    使用函數的目的也是為了把反復編寫的模板代碼封裝起來,如果其他地方需要用到的話,可以直接想調用函數的方式進行獲取

    如果有多處用到重復的模板代碼,那麽可以單獨創建一個HTML文件,用來存放宏。然後在需要用到的地方包含這個文件。

      {% import ‘macro.html‘ as functions %}

      {{ functions.func() }}

  (3). 包含:{% include ‘hello.html‘ %}

    包含相當於把被包含的文件(hello.html)重新復制了一份到當前文件,然後再返回給瀏覽器。

    如果被包含的文件不存在,那麽會發生TemplateNotFound錯誤。通過添加 ignore missing關鍵字來忽略這個錯誤。

    

  (4). 小結:

    繼承、宏、包含都可以實現代碼復用的功能,其中繼承相對來說用的比較廣泛一些!

    繼承的本質是對父模板中的某段代碼進行重寫,一般用來實現多個頁面中重復不變的區域,如頂部和底部。

    宏就相當於函數,可以傳入參數,定義,然後再進行調用

    包含是直接將目標模板文件整個渲染出來,相當於復制了一份。

三、CSRF

  1. 什麽是CSRF?

   CSRF的全稱是:跨站請求偽造(Cross Site Request Forgery)。是指攻擊者獲取了用戶的一些私人信息,然後去攻擊信任用戶的網站!

  2. 攻擊原理圖:

   技術分享圖片

  3. 如何采取安全措施呢?

   比較csrf_token,即當用戶請求時服務器端設置一個csrf_token給客戶端,保存在瀏覽器中;同時當用戶執行form表單提交操作時,需要把csrf_token一起和其他參數給提交上來,但是這個參數不是用戶自己輸入的,而是服務器端把它隱藏在表單中。在服務器端把來自請求中cookie裏的csrf_token和post請求中攜帶的csrf_token參數進行對比,如果不相等,那麽就不能繼續往下執行。如果成功的話,說明有可能是安全訪問!為什麽是有可能呢?因為可能你設置csrf_token的原理被別人截取到了,那麽也就無效了!所以這個設置只能針對一般的,對技術不是太好的人有效。

   這也就是為什麽Flask-WTF擴展包中,如果需要使用裏面的form表單,必須要設置一個csrf_token, 然後在配置文件中設置SECRET_KEY。

  

Python框架學習之Flask中的Jinja2模板