200行代碼實現web框架(三):動手寫個模板引擎
閱讀本文之前,請先閱讀之前的文章:
200行代碼實現web框架(一):裝飾器實現簡單路由功能
200行代碼實現web框架(二):werkzeug大法好!
為了實現前後端分離,我們的web框架需要一個模板功能。
模板引擎的工作原理並不複雜,最常用的模板引擎是「替換式」的,可以理解為做個填空題。在這裡,我們採用正則表達式替換關鍵字標記的策略來用幾十行代碼實現一個簡單的模板引擎。
Flask使用Jinja2作為其模板引擎,在Flask中,我們可以通過下列語句輕鬆渲染模板:
render_template(index.html, name="Lee")n
同樣,我們也採用類似的方法,構建一個render_template函數,將模板名和關鍵字作為參數傳入,對模板文件進行渲染。
Jinja2中採用類似於下面這樣的語法來對關鍵字進行標記:
{{name}}n
我們可以採用相同的關鍵字標記方法。
模板文件默認存放在templates文件夾內。
首先,構建正則表達式,對模板文件進行解析,定義一個parse_template函數,這個函數的功能是將模板中被標記的關鍵字提取並返回:
import os, rennntemplate_folder = "templates"npattern = r{{(.*?)}}nndef parse_template(template_file):n #將返回模板中所有被"{{}}"包起來的內容n return re.compile(pattern).findall(template_file)n
下面來實現render_template函數。這個函數要完成的任務是把html文件中被解析出來的關鍵字依次替換成我們想要替換的內容,我們稱這一步為「渲染」:
def render_template(template_file,**kws):nn file = os.path.join(template_folder, template_file)n if os.path.exists(file):n with open(file, rb) as f:n text = f.read().decode()n #解析關鍵字n args = parse_template(text)n #替換關鍵字n if kws:n for arg in args:n text = text.replace("{{%s}}" % arg, str(kws.get(arg)))nn return textn
我們將上面的代碼存儲為template.py文件,全文如下:
# -*- coding: utf-8 -*-n# template.pynimport os, renntemplate_folder = "templates"npattern = r{{(.*?)}}nndef parse_template(template_file):n #將返回模板中所有被"{{}}"包起來的內容n return re.compile(pattern).findall(template_file)nndef render_template(template_file,**kws):nn file = os.path.join(template_folder, template_file)n if os.path.exists(file):n with open(file, rb) as f:n text = f.read().decode()nn args = parse_template(text)n print argsn if kws:n for arg in args:n text = text.replace("{{%s}}" % arg, str(kws.get(arg)))nn return textn
假設我們在app中註冊了一個可以顯示用戶id的頁面:
@app.route(/id/<int:id>)ndef id(request):n urls = app.bind_to_environ(request.environ)n values = urls.match()[1]n return Response(render_template("id.html", id = values["id"]),n content_type = "text/html")n
運行伺服器,當我們在瀏覽器中訪問localhost:8000/id/80的時候,我們希望頁面上顯示80這個數字。為這個頁面編寫模板並存在templates文件夾下的id.html中:
<html>n <body>n <h1>Your ID is: {{id}}</h1>n </body>n</html>n
這樣就實現了一個簡單的模板,當然這個模板只具有替換關鍵字的功能,其它一些高大上的功能比如繼承和條件語句則需要更加複雜的代碼……
參考閱讀:
淺談模板引擎 - 木的樹 - 博客園
介紹 - Jinja2 2.7 documentation
推薦閱讀:
※nodejs 和 homebridge
※2 列縮進相比 4 列縮進有什麼壞處?
※2018 最好的自動化測試工具(Top 10 回顧)