[叁]Flask web開發(fā):模板

本系列筆記是我閱讀Miguel Grinberg的《Flask Web Development》的筆記,標(biāo)題與書本同步。希望通過記錄技術(shù)筆記的方式促進(jìn)自己對知識的理解。本篇對應(yīng)書本第三章:模板。

模板是一個(gè)包含響應(yīng)文本的文件,其中包含用占位變量表示的動(dòng)態(tài)部分,其具體值只在請求的上下文中才能知道。使用真實(shí)值替代變量,再返回最終得到的響應(yīng)字符串,這一過程成為渲染。

Jinja2模板引擎

Flask渲染模板使用的是Jinja2模板引擎。

渲染模板

hello.py 渲染模板
from flask import Flask,render_template

#...

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/user/<name>')
def user(name):
    return render_template('user.html',name=name)
    
# Flask提供的render_template函數(shù)把Jinja2模板引擎集成到了程序中。
# render_template函數(shù)的第一個(gè)參數(shù)是模板的文件名。
# 隨后的參數(shù)都是鍵值對,表示模板中變量對應(yīng)的真實(shí)值。

變量

模板中使用的{{ name }}結(jié)構(gòu)表示一個(gè)變量,它是一種特殊的占位符,告訴模塊引擎這個(gè)位置的值從渲染模板時(shí)使用的數(shù)據(jù)中獲取。

Jinja2能識別所有類型的變量,示例:

<p>A value from a dictionary:{{ mydict['key']}}.</p>
<p>A value from a list:{{ mylist[3]}}.</p>
<p>A value from a list,with a variable index:{{ mylist[myintvar] }}.</p>
<p>A value from an object's method: {{ myobj.somemethod() }}.</p>

變量過濾器

過濾器名添加在變量之后,中間使用豎線分隔。

hello, {{ name|capitalize }}

常用過濾器:

過濾器名 說明
safe 渲染值時(shí)不轉(zhuǎn)義
capitalize 把值得首字母轉(zhuǎn)換成大寫,其他字母轉(zhuǎn)換成小寫
lower 把值轉(zhuǎn)換成小寫形式
upper 把值轉(zhuǎn)換成大寫形式
title 把值中每個(gè)單詞的首字母都換成大寫
trim 把值的首位空格去掉
striptags 渲染之前把值中所有的HTML標(biāo)簽都刪掉

控制結(jié)構(gòu)

條件控制結(jié)構(gòu)

{% if user %}
    Hello,{{ user }}!
{% else %}
    Hello, Stranger!
{% endif %}

渲染一組元素

<ul>
    {% for comment in comments %}
        <li>{{ comment }}</li>
    {% endfor %}
</ul>

{{% macro render_comment(comment)%}}
    <li>{{ comment }}</li>
{{ endmacro }}

<ul>
    {% for comment in comments %}
        {{ render_comment(comment) }}
    {% endfor %}
</ul>

為了重復(fù)使用宏,保存在單獨(dú)文件中,再在需要的模板中導(dǎo)入。
{% import 'macro.html' as macros %}
<ul>
    {% for comment in comments%}
        {{ macros.render_comment(comment)}}
    {% endfor%}
</ul>

復(fù)用代碼片段

{% include 'common.html' %}

模板繼承

- 建一個(gè)名為base.html的基模板
<html>
<head>
    {% block head %}
    <title>{% block title %}{% endblock %} - My Application</title>
    {% endblock %}
</head>
<body>
    {% block body %}
    {% endblock %}
</body>
</html>

- 衍生模板中修改block標(biāo)簽定義的元素
{% extends "base.html" %} #定義基模板
{% block title%}Index{% endblock %} #修改title塊內(nèi)容
{% block head %} #修改head塊內(nèi)容
    {{ super() }} #原來head中有內(nèi)容,用super()獲取原來的內(nèi)容
    <style>
    </style>
{% endblock %}
{% block body %} #修改body塊內(nèi)容
<h1>Hello, World!</h1>
{% endblock %}

使用Flask-Bootstrap集成Twitter Bootstrap

Bootstrap是Twitter開發(fā)的一個(gè)開源框架,它提供用戶界面組件可用于創(chuàng)建整潔且具有吸引力的網(wǎng)頁,而且這些網(wǎng)頁還能兼容所有現(xiàn)代Web瀏覽器。Bootstrap是客戶端框架,不會(huì)直接涉及服務(wù)器。可以在模板中引用Bootstrap的CSS和JavaScript文件。

安裝Flask-Bootstrap擴(kuò)展

(venv)$ pip install flask-bootstrap

hello.py: 初始化Flask-Bootstrap
from falsk_bootstrap import Bootstrap
# ...
bootstrap = Bootstrap(app)

使用Flask-Bootstrap的模板

{% extends "bootstrap/base.html" %}

{% block title%}Flasky{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
    <div class='container'>
        <div class="navbar-header">
            <button type="button" class="navbar-toggle"
            data-toggle="collapse" data-target=".navbar-collapse">
            <span class="sr-only">Toggle navigation</span>
            <span class='icon-bar'></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Flasky</a>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/"></a></li>
            </ul>
        </div>
    </div>
</div>
{% endblock %}

{% block content %}
<div class="container">
    <div class="page-header">
        <h1>Hello,{{ name }}!</h1>
    </div>
</div>
{% endblock %}
# 模板利用Bootstrap中的樣式進(jìn)行了修改

Flask-Bootstrap基模板中定義的塊

塊名 說明
doc 整個(gè)HTML文檔
html_attribs <html>標(biāo)簽的屬性
html <html>標(biāo)簽中的內(nèi)容
head <head>標(biāo)簽中的內(nèi)容
title <title>標(biāo)簽中的內(nèi)容
metas 一組<meta>標(biāo)簽
styles 層疊樣式表定義
body_attribs <body>標(biāo)簽的屬性
body <body>標(biāo)簽中的內(nèi)容
navbar 用戶定義的導(dǎo)航條
content 用戶定義的頁面內(nèi)容
scripts 文檔底部的JavaScript聲明

自定義錯(cuò)誤頁面

利用Jinja2的模板繼承機(jī)制可以讓templates/base.html繼承自bootstrap/base.html。

{% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Flasky</a>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/">Home</a></li>
            </ul>
        </div>
    </div>
</div>
{% endblock %}

{% block content %}
<div class="container">
    {% block page_content %}{% endblock %}
</div>
{% endblock %}

程序現(xiàn)在使用的模板繼承自templates/base.html不是直接繼承自Flask-Bootstrap的基模板。

404錯(cuò)誤頁面:繼承自templates/base.html
{% extends "base.html" %}

{% block title %}Flasky - Page Not Found{% endblock %}

{% block page_content %}
<div class="page-header">
    <h1>Not Found</h1>
</div>
{% endblock %}

user頁面:繼承自templates/base.html
{% extends "base.html" %}

{% block title %}Flasky{% endblock %}

{% block page_content %}
<div class="page-header">
    <h1>Hello, {{ name }}!</h1>
</div>
{% endblock %}

鏈接

Flask提供了url_for()輔助函數(shù),它可以使用程序URL映射中保存的信息生成URL。

  • url_for函數(shù)最簡單的用法:以視圖函數(shù)名作為參數(shù),返回對應(yīng)的URL。url_for('index')得到的結(jié)果是'/'
  • 使用url_for生成動(dòng)態(tài)地址時(shí),將動(dòng)態(tài)部分作為關(guān)鍵字參數(shù)傳入。
    url_for('user',name='john',_external=True)
  • 函數(shù)能將任何額外參數(shù)添加到查詢字符串中。

靜態(tài)文件

使用Flask-Moment本地化日期和時(shí)間

Flask-Moment是Flask的一個(gè)程序擴(kuò)展,能夠在瀏覽器中渲染日期和時(shí)間。

安裝Flask-Moment
(venv)$ pip install flask-moment

hello.py:初始化Flask-Moment

from flask_moment import Moment
moment = Moment(app)

templates/base.html: 引入 moment.js庫

{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}

hello.py: 加入一個(gè)datetime變量

from date.time import datetime

@app.route('/')
def index():
    return render_template('index.html',current_time=datetime.utcnow())

templates/index.html: 使用Flask-Moment渲染時(shí)間戳

    <p>The local date and time is {{ moment(current_time).format('LLL') }}.</p>
    <p>That was {{ moment(current_time).fromNow(refresh=True) }}.</p>

本文由 EverFighting 創(chuàng)作,采用 **知識共享署名 3.0 中國大陸許可協(xié)議 **進(jìn)行許可。
可自由轉(zhuǎn)載、引用,但需署名作者且注明文章出處。

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

推薦閱讀更多精彩內(nèi)容