Day02 Jinja2模板引擎, 使用Twitter Bootstrap

源代碼: https://github.com/ltoddy/flask-tutorial

技術(shù)交流群:630398887(歡迎一起吹牛)

有些地方?jīng)]看懂沒關(guān)系每强,堅持往下看胡野,下面會有演示代碼來說明。

上一篇中如下代碼

@app.route('/')
def hello_world():
    return 'Hello World!'

這個樣子返回一個字符串昌罩,很不爽阱穗,能不能直接返回一個HTML頁面饭冬,當(dāng)然可以。

在templates文件夾下新建一個index.html

<small>templates/index.html</small>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Just for fun</title>
</head>
<body>

<h1>Hello World</h1>

</body>
</html>

<small>blog.py</small>

from flask import render_template
#...
@app.route('/')
def hello_world():
    return render_template('index.html')

這個樣子就直接把那個index.html頁面顯示了出來.

Jinja2模板引擎

渲染模板

在blog.py的def user(username) 這個函數(shù)中,如果我們想把那個username傳入html頁面怎么辦呢?
在templates文件夾下新建user.html

<small>templates/user.html</small>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Just for fun</title>
</head>
<body>

<h1>Hello {{ name }}.</h1>

</body>
</html>

視圖函數(shù)user()返回的響應(yīng)中包含一個使用變量表示的動態(tài)部分.
<small>blog.py</small>

@app.route('/<username>')
def user(username):
    return render_template('user.html', name=username)

注意看這里的對應(yīng)關(guān)系,在return那里,render_template接受了如下兩個部分:

  • 'user.html' 這個是要展現(xiàn)的頁面名字,頁面要放在templates文件夾下,jinja2引擎會自動去templates文件夾尋找此文件.
  • 第二部分就是user.html中所需要的參數(shù),這里可以有很多個參數(shù),下文將會看到.在這里,name=username,左邊的name表示參數(shù)名,就是模板中使用的占位符,右邊的username是當(dāng)前作用域中的變量.

變量

剛才使用的{{ name }}結(jié)構(gòu)表示一個變量,它是一個特殊的占位符,告訴模板引擎這個位置的值從渲染模板時使用的數(shù)據(jù)中獲取.
Jinja2能識別所有類型的變量,甚至是一些特殊的類型:例如列表,字典和對象.
e.g.

  • <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 a object's method: {{ myobj.somemethod() }}.</p>

Jinja2另外也提供了叫 過濾器 的東西揪阶,但是不怎么用昌抠,這里就不再說明了。

Jinja2過濾器完整文檔

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

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

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

循環(huán)控制結(jié)構(gòu)

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

需要在多出重復(fù)使用的模板代碼片段可以寫入單獨的文件,再包含在所有模板中,以避免重復(fù):

{% include 'common.html' %}

另一種重復(fù)使用代碼的強大方式是模板繼承.
首先創(chuàng)建一個名為base.html的模板

<html lang="en">
<head>
    {% block head %}
        <title>{% block title %}{% endblock %} - My Application</title>
    {% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>

block標簽定義的元素可在衍生模板中修改.例如

{% extends 'base.html' %}
{% block title %}Index{% endblock %}
{% block head %}
    {{ super() }}
    <style>
    </style>
{% endblock %}
{% block body %}
<h1>Hello, World!</h1>
{% endblock %}

block標簽定義的元素可以在衍生的模板中修改.
extends指令聲明這個模板衍生自base.html.在extends指令之后,基模板中的3個塊被重新定義,模板引擎會將其插入適當(dāng)?shù)奈恢?

使用Flask-Bootstrap集成Twitter Bootstrap

如果電腦上有pip的可以:

pip install flask-bootstrap

沒有的就如上篇文章那樣,通過Pycharm自動幫你安裝.
Bootstrap CSS樣式庫,簡單點理解就是你獲得了一大堆化妝品(定制好的,而非按照自己想法定制的樣子),可以有選擇的去使用.

初始化Flask-Bootstrap:

from flask_bootstrap import Bootstrap
# ...
bootstrap = Bootstrap(app)

待會要通過繼承Bootstrap的base.html頁面來實現(xiàn)模板的復(fù)用.
先看看bootstrap的base.html為我們提供了什么:

{% block doc -%}
    <!DOCTYPE html>
    <html{% block html_attribs %}{% endblock html_attribs %}>
    {%- block html %}
        <head>
            {%- block head %}
                <title>{% block title %}{% endblock title %}</title>

                {%- block metas %}
                    <meta name="viewport" content="width=device-width, initial-scale=1.0">
                {%- endblock metas %}

                {%- block styles %}
                    <!-- Bootstrap -->
                    <link href="{{ bootstrap_find_resource('css/bootstrap.css', cdn='bootstrap') }}" rel="stylesheet">
                {%- endblock styles %}
            {%- endblock head %}
        </head>
        <body{% block body_attribs %}{% endblock body_attribs %}>
        {% block body -%}
            {% block navbar %}
            {%- endblock navbar %}
            {% block content -%}
            {%- endblock content %}

            {% block scripts %}
                <script src="{{ bootstrap_find_resource('jquery.js', cdn='jquery') }}"></script>
                <script src="{{ bootstrap_find_resource('js/bootstrap.js', cdn='bootstrap') }}"></script>
            {%- endblock scripts %}
        {%- endblock body %}
        </body>
    {%- endblock html %}
    </html>
{% endblock doc -%}

主要用到兩個塊: navbar(導(dǎo)航欄)和content(頁面主要內(nèi)容).

在templates文件夾下新建base.html文件

<small>templates/base.html</small>

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

{% block title %}Just for fun{% endblock %}

{% block navbar %}
    <nav class="navbar navbar-inverse">
        <div class="container-fluid">
            <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="/">Just for fun</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/">Home</a></li>
                </ul>
            </div>
        </div>
    </nav>
{% endblock %}

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

然后我們更改一下index.html和user.html
<small>templates/index.html</small>

{% extends 'base.html' %}

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

<small>templates/user.html</small>

{% extends 'base.html' %}

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

OK,我們運行一下看看效果:



還不錯.

自定義錯誤頁面.

有時候輸入一個錯誤的網(wǎng)址的時候,會返回一個404 page not found錯誤.
分別在templates文件夾下創(chuàng)建404.html和500.html

<small>templates/404.html</small>

{% extends 'base.html' %}

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

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

<small>templates/500.html</small>

{% extends 'base.html' %}

{% block title %}500 - Internal Server Error{% endblock %}

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

以及我們要在blog.py中添加相應(yīng)的路由:
<small>blog.py</small>

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500

看一下blog.py的完整代碼:
<small>blog.py</small>

from flask import Flask
from flask import render_template
from flask_bootstrap import Bootstrap

app = Flask(__name__)
bootstrap = Bootstrap(app)


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


@app.route('/<username>')
def user(username):
    return render_template('user.html', name=username)


@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500


if __name__ == '__main__':
    app.run(debug=True)

在最后一行,我加入了:debug=True,目的是當(dāng)你對程序做出了改變之后,不需要手動重啟項目,項目會自動幫你做出重啟.

最后說一點內(nèi)容,下一篇將會用到

使用Flask-Script支持命令行選項

安裝Flask-Script:

pip install flask-script

Flask的開發(fā)web服務(wù)器支持很多啟動設(shè)置選項,傳遞設(shè)置選項的理想方式是使用命令行參數(shù).

e.g.:

from flask_script import Manager
manager = Manager(app)

# ...

if __name__ == '__main__':
    manager.run()

此時的完整代碼:
<small>blog.py</small>

from flask import Flask
from flask import render_template
from flask_bootstrap import Bootstrap
from flask_script import Manager

app = Flask(__name__)
bootstrap = Bootstrap(app)
manager = Manager(app)


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


@app.route('/<username>')
def user(username):
    return render_template('user.html', name=username)


@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500


if __name__ == '__main__':
    manager.run()

現(xiàn)在如何啟動程序遣钳?

在軟件的左下角,選擇點擊Terminal,
輸入:

python3 blog.py runserver

如下:



這里要注意一下,我目前使用的是我的Linux系統(tǒng),Python2和Python3都有,所以這里寫明是Python3,如果你電腦上只有Python3,那么你把這里的python3替換成python就可以了.按照自己電腦為主.

然后打開瀏覽器,在地址欄填入: http://localhost:5000/ 回車就可以了.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扰魂,一起剝皮案震驚了整個濱河市麦乞,隨后出現(xiàn)的幾起案子蕴茴,更是在濱河造成了極大的恐慌,老刑警劉巖姐直,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倦淀,死亡現(xiàn)場離奇詭異,居然都是意外死亡声畏,警方通過查閱死者的電腦和手機撞叽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來插龄,“玉大人愿棋,你說我怎么就攤上這事【危” “怎么了糠雨?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長徘跪。 經(jīng)常有香客問我甘邀,道長,這世上最難降的妖魔是什么垮庐? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任松邪,我火速辦了婚禮,結(jié)果婚禮上哨查,老公的妹妹穿的比我還像新娘逗抑。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布邮府。 她就那樣靜靜地躺著浙于,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挟纱。 梳的紋絲不亂的頭發(fā)上羞酗,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音紊服,去河邊找鬼檀轨。 笑死,一個胖子當(dāng)著我的面吹牛欺嗤,可吹牛的內(nèi)容都是我干的参萄。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼煎饼,長吁一口氣:“原來是場噩夢啊……” “哼讹挎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吆玖,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤筒溃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后沾乘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怜奖,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年翅阵,在試婚紗的時候發(fā)現(xiàn)自己被綠了歪玲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡掷匠,死狀恐怖滥崩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情讹语,我是刑警寧澤钙皮,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站募强,受9級特大地震影響株灸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜擎值,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一慌烧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸠儿,春花似錦屹蚊、人聲如沸厕氨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽命斧。三九已至,卻和暖如春嘱兼,著一層夾襖步出監(jiān)牢的瞬間国葬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工芹壕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留汇四,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓踢涌,卻偏偏與公主長得像通孽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子睁壁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

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