Flask學習日志(六) - Flask模板

每日壁紙.jpg

文 / 秦未

1.jinja2解析

今天學習Flask的模板引擎 -- jinja2,我們先看看它工作的原理:

jinja2工作原理.png

說明:視圖函數通過上下文與模板之間傳遞數據,模板由jinja2引擎驅動支持并生成HTML文件,這樣展示在客戶端瀏覽器中的內容就是完整的頁面了。

我們之前有一個范例:

@app.route('/about')
def about():
    return '<h1>about</h1>'

我們改變一下:

@app.route('/about')
def about():
    return render_template('blog/about.html', **{
        'text': 'Hello, World',
    })

其中about.html內容 :

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>關于頁面</title>
</head>
<body>

{{ text }}

</body>
</html>

運行輸出:

運行狀態1.png

其中我們發現h1并沒有生效,而是作為字符串完整的顯示了出來,其實這是jinja2的自動轉義功能在起作用,主要目的是防止跨站腳本攻擊。

但如果我們能保證內容是安全的,我們想要實現標簽的作用該怎么辦呢?

jinja2提供兩種辦法禁用自動轉義功能。

1.塊元素包裹內容:

{#/app/templates/blog/about.html#}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>關于頁面</title>
</head>
<body>

{% autoescape false%}
{{ text }}
{% endautoescape %}

</body>
</html>

說明:在{% autoescape false%}{% endautoescape %}內包裹的所有內容都會被禁止自動轉義。

2.單獨的

{#/app/templates/blog/about.html#}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>關于頁面</title>
</head>
<body>

{{ text|safe }}

</body>
</html>

說明:在指定值后面加 “|safe”,即可在這個值中禁用自動轉義。

最后效果是一樣的:

運行效果2.png

第二種方法其實是模板引擎的過濾器,本質來說這是一種值的預處理方法(函數),每一個過濾器代表一個方法(函數),它接收|之前的參數,然后輸出內容在當前位置,在模板中一個變量可同時使用多個過濾器,解析從左往右。

jinja2本身提供了相當多的過濾器,正常情況下足夠我們使用了,當然我們也可以自定義過濾器。

2.自定義過濾器示例:

我們需要一個markdown過濾器,官方并沒有提供。

首先下載一個mistune模塊,這個markdown解析庫是Python中最快的,據稱比Markdown模塊快10倍左右。

pip install mistune

然后在app.py 內增加一個裝飾器加函數:

# /app/app.py
@app.template_filter('md')
def markdown_to_html(text):
    import mistune
    markdown = mistune.Markdown()
    return markdown(text)

同時為了驗證,修改about函數:

# /app/app.py
@app.route('/about')
def about():
    return render_template('blog/about.html', **{
        'text': '<h1>Hello, World</h1>',
        'body': '## 演示'
    })

about.html也要修改:

{#/app/templates/blog/about.html#}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>關于頁面</title>
</head>
<body>

{{ text|safe }}
{{ body|md|safe }}
</body>
</html>

運行效果:

運行效果3.png

有時候,我們想在前臺運行一個函數怎么辦?

比如我們想實現一個功能:定義一個函數讀取目錄下的md文件并輸出到前臺。

先看源碼:

# /app/app.py
def read_md(filename):
    from functools import reduce
    # 獲取當前路徑
    basepath = path.abspath(path.dirname(__file__))
    # 將路徑連接
    upload_path = path.join(basepath, filename)
    with open(upload_path, encoding='UTF-8') as md_file:
        # reduce為歸納的意思,主要作用是讓獲取的每一行都加上前一行。
        content = reduce(lambda x, y: x + y, md_file.readlines())
    return content

# 將read_md函數傳遞到前臺
@app.context_processor
def inject_methods():
    return dict(read_md=read_md)

先建立一個在app目錄下的名叫md.md的文件:

![每日壁紙.jpg](http://upload-images.jianshu.io/upload_images/3980526-b9539b5712fcccee.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

## 1.jinja2解析
今天學習Flask的模板引擎 -- jinja2,我們先看看它工作的原理:

使用:

{#/app/templates/blog/about.html#}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>關于頁面</title>
</head>
<body>

{{ text|safe }}
{{ body|md|safe }}
{{ read_md('md.md')|md|safe }}

</body>
</html>

{{ read_md('md.md')|md|safe }}這段代碼從左往右執行,先執行這個函數read_md('md.md'),再將獲取的內容轉換為HTML,同時這個內容不需要轉義。

運行效果:

運行狀態4.png

---end---

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容