03.flask模板


配套視頻教程

本文B站配套視頻教程

模板概述

一. 為什么要使用模板

視圖函數有兩個作用, 一個是業務邏輯一個是表現邏輯, 舉例說明:

用戶在網站注冊了一個新賬號, 用戶在表單中輸入電子郵件地址和密碼, 點擊提交按鈕, 服務器接收到包含用戶輸入的請求, 然后Flask把請求分發到處理注冊請求的視圖函數。 這個視圖函數需要訪問數據庫, 添加新用戶(業務邏輯), 然后生成相應回送瀏覽器(表現邏輯)。

兩個完全獨立的作用被混淆到一起會使代碼難以理解和維護, 所以我們選擇把表現邏輯(響應)遷移到模板當中去。

模板是包含響應文本的文件,其中包含用占位變量表示的動態部分,其具體值只在請求的上下文中才能知道。使用真實值替換變量,再返回最終得到的響應字符串,這一過程稱為渲染。為了渲染模板,Flask 使用一個名為 Jinja2 的強大模板引擎。

二. 如何使用模板

  1. 如何渲染模板:
    • 模板放在templates文件夾下
    • flask中導入render_template函數。
    • 在視圖函數中,使用render_template函數,渲染模板。注意:只需要填寫模板的名字,不需要填寫templates這個文件夾的路徑。
  2. 模板傳參:
    • 如果只有一個或者少量參數,直接在render_template函數中添加關鍵字參數就可以了。
    • 如果有多個參數的時候,那么可以先把所有的參數放在字典中,然后在render_template中,
      使用兩個星號,把字典轉換成關鍵參數傳遞進去,這樣的代碼更方便管理和使用。
  3. 在模板中,如果要使用一個變量,語法是:{{params}}
  4. 訪問模型中的對象屬性或者是字典,可以通過{{params.property}}的形式,或者是使用{{params['age']}}.

示例代碼

template01 .py

#encoding: utf-8
from flask import Flask,render_template

app = Flask(__name__)

@app.route('/')
def index():
    # 類
    class Person(object):
        name = u'p17bdw'
        age = 18

    p = Person()

    context = {
        'username': u'c17bdw',
        'gender': u'男',
        'age': 17,
        'person': p,    # 聲明
        'websites': {
            'baidu': 'www.baidu.com',
            'google': 'www.google.com'
        }
    }
    return render_template('anthoer/index.html',**context)

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

anthoer/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    這是HTML文件中出現的文字
    <p>用戶名:{{ username }}</p>
    <p>性別:{{ gender }}</p>
    <p>年齡:{{ age }}</p>

    <hr>
    <p>名字:{{ person['name'] }}</p>
    <p>年齡:{{ person.age }}</p>

    <hr>
    <p>百度:{{ websites['baidu'] }}</p>
    <p>谷歌:{{ websites['google'] }}</p>
</body>
</html>

if判斷

  1. 語法:
    {% if xxx %} {% else %} {% endif %}

  2. if的使用,可以和python中相差無幾。

示例代碼

if_statement .py

# 輸入 http://127.0.0.1:5000/1/ 為登錄狀態,否則為未登錄狀態。

#encoding: utf-8

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/<is_login>/')
def index(is_login):
    if is_login == '1':
        user = {
            'username': u'17bdw',
            'age':20
        }
        return render_template('index.html',user=user)
    else:
        return render_template('index.html')

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

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    {% if user and user.age > 18 %}
        <a href="#">{{ user.username }}</a>
        <a href="#">注銷</a>
    {% else %}
        <a href="#">登錄</a>
        <a href="#">注冊</a>
    {% endif %}
</body>
</html>

for循環遍歷列表和字典

1.  字典的遍歷,語法和`python`一樣,可以使用`items()`、`keys()`、`values()`、`iteritems()`、`iterkeys()`、`itervalues()`
    `{% for k,v in user.items() %} <p>{{ k }}:{{ v }}</p> {% endfor %}`
2.  列表的遍歷:語法和`python`一樣。
    `{% for website in websites %} <p>{{ website }}</p> {% endfor %}`

示例代碼

for_statement .py

#encoding: utf-8

from flask import Flask,render_template

app = Flask(__name__)

# for遍歷字典

@app.route('/')
def index():
    books = [
        {
            'name': u'西游記',
            'author': u'吳承恩',
            'price': 109
        },
        {
            'name': u'紅樓夢',
            'author': u'曹雪芹',
            'price': 200
        },
        {
            'name': u'三國演義',
            'author': u'羅貫中',
            'price': 120
        },
        {
            'name': u'水滸傳',
            'author': u'施耐庵',
            'price': 130
        }
    ]
    return render_template('index.html',books=books)

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

index.html

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

<table>
    <thead>
        <th>書名</th>
        <th>作者</th>
        <th>價格</th>
    </thead>
    <tbody>
        {% for book in books %}
            <tr>
                <td>{{ book.name }}</td>
                <td>{{ book.author }}</td>
                <td>{{ book.price }}</td>
            </tr>
        {% endfor %}
    </tbody>
</table>

</body>
</html>

過濾器

  1. 介紹和語法:

    • 介紹:過濾器可以處理變量,把原始的變量經過處理后再展示出來。作用的對象是變量。
    • 語法:
      {{ avatar|default('xxx') }}
  2. default過濾器:如果當前變量不存在,這時候可以指定默認值。

  3. length過濾器:求列表或者字符串或者字典或者元組的長度。

  4. 常用的過濾器:
    abs(value):返回一個數值的絕對值。示例:-1|abs
    default(value,default_value,boolean=false):如果當前變量沒有值,則會使用參數中的值來代替。示例:name|default('xiaotuo')——如果name不存在,則會使用xiaotuo來替代。boolean=False默認是在只有這個變量為undefined的時候才會使用default中的值,如果想使用python的形式判斷是否為false,則可以傳遞boolean=true。也可以使用or來替換。
    escape(value)或e:轉義字符,會將<、>等符號轉義成HTML中的符號。示例:content|escape或content|e。
    first(value):返回一個序列的第一個元素。示例:names|first
    last(value):返回一個序列的最后一個元素。示例:names|last。

    length(value):返回一個序列或者字典的長度。示例:names|length。
    join(value,d=u''):將一個序列用d這個參數的值拼接成字符串。
    safe(value):如果開啟了全局轉義,那么safe過濾器會將變量關掉轉義。示例:content_html|safe。
    int(value):將值轉換為int類型。
    float(value):將值轉換為float類型。
    lower(value):將字符串轉換為小寫。
    upper(value):將字符串轉換為小寫。
    replace(value,old,new): 替換將old替換為new的字符串。
    truncate(value,length=255,killwords=False):截取length長度的字符串。
    striptags(value):刪除字符串中所有的HTML標簽,如果出現多個空格,將替換成一個空格。
    trim:截取字符串前面和后面的空白字符。
    string(value):將變量轉換成字符串。
    wordcount(s):計算一個長字符串中單詞的個數。

示例代碼

filter_demo .py

#encoding: utf-8

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/')
def index():
    comments = [
        {
            'user': u'admin',
            'content': 'xxxx'
        },
        {
            'user': u'tesr',
            'content': 'xxxx'
        }
    ]
    return render_template('index.html',comments=comments)

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

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>過濾器</title>
</head>
<body>

# 如果avatar這個變量不存在,就使用default過濾器提供的值

<img src="{{ avatar|default('http://avatar.csdn.net/1/D/B/3_hmzkekek41.jpg') }}" alt="">

<hr>

# length 計算長度
<p>評論數:({{ comments|length }})</p>
<ul>
    {% for comment in comments %}
        <li>
            <a href="#">{{ comment.user }}</a>
            <p>{{ comment.content }}</p>
        </li>
    {% endfor %}

</ul>
</body>
</html>

繼承和block

  1. 繼承作用和語法:

    • 作用:可以把一些公共的代碼放在父模板中,避免每個模板寫同樣的代碼。
    • 語法:

    {% extends 'base.html' %}

  2. block實現:

    • 作用:可以讓子模板實現一些自己的需求。父模板需要提前定義好。
    • 注意點:字模板中的代碼,必須放在block塊中。

示例代碼

app.py

#encoding: utf-8

from flask import Flask,render_template

app = Flask(__name__)

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

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

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

index.html


{% extends 'base.html' %}

{% block head %}
    <style>

    </style>
    <link rel="stylesheet" href="">
    <script></script>
{% endblock %}

{% block title %}
    首頁
{% endblock %}

{% block main %}
    <h1>這是首頁</h1>
{% endblock %}

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
        <style>
        .nav{
            background: #3a3a3a;
            height: 65px;
        }
        ul{
            overflow: hidden;
        }
        ul li{
            float: left;
            list-style: none;
            padding: 0 10px;
            line-height: 65px;
        }
        ul li a{
            color: #fff;
        }
    </style>
    {% block head %}{% endblock %}
</head>
<body>
<div class="nav">
    <ul>
        <li><a href="/">首頁</a></li>
        <li><a href="/login">發布問答</a></li>
    </ul>
</div>
{% block main %}{% endblock %}
</body>
</html>

login.html

{% extends 'base.html' %}

{% block title %}
    登錄
{% endblock %}

{% block main %}
    <h1>這是登錄頁面</h1>
{% endblock %}

使用Flask-Bootstrap集成Bootstrap

Bootstrap 是 Twitter 開發的一個開源 Web 框架,它提供的用戶界面組件可用於創建整潔且具有吸引力的網頁,而且兼容所有現代的桌面和移動平台 Web 瀏覽器。

要想在應用中集成 Bootstrap,最直接的方法是根據 Bootstrap 文檔中的說明對 HTML 模板進行必要的改動。不過,這個任務使用 Flask 擴展處理要簡單得多,而且相關的改動不會導致主邏輯凌亂不堪。

我們要使用的擴展是 Flask-Bootstrap,它可以使用 pip 安裝:

(venv) $ pip install flask-bootstrap

Flask 擴展在創建應用實例時初始化。

初始化 Flask-Bootstrap。

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

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

擴展通常從 flask_<name> 包中導入,其中 <name> 是擴展的名稱。多數 Flask 擴展采用兩種初始化方式中的一種。在示例中,初始化擴展的方式是把應用實例作為參數傳給構造函數。

初始化 Flask-Bootstrap 之后,就可以在應用中使用一個包含所有 Bootstrap 文件和一般結構的基模板。應用利用 Jinja2 的模板繼承機制來擴展這個基模板。

templates/user.html:使用 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="/">Home</a></li>
            </ul>
        </div>
    </div>
</div>
{% endblock %}

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

Jinja2 中的 extends 指令從 Flask-Bootstrap 中導入 bootstrap/base.html,從而實現模板繼承。Flask-Bootstrap 的基模板提供了一個網頁骨架,引入了 Bootstrap 的所有 CSS 和 JavaScript 文件。

上面這個 user.html 模板定義了 3 個區塊,分別名為 titlenavbar 和 content。這些區塊都是基模板提供的,可在衍生模板中重新定義。title 區塊的作用很明顯,其中的內容會出現在渲染后的 HTML 文檔頭部,放在 <title> 標簽中。navbar 和 content 這兩個區塊分別表示頁面中的導航欄和主體內容。

在這個模板中,navbar 區塊使用 Bootstrap 組件定義了一個簡單的導航欄。content 區塊中有個 <div> 容器,其中包含一個頁頭。之前版本中的歡迎消息,現在就放在這個頁頭里。改動之后的應用如圖所示。

url鏈接

使用url_for(視圖函數名稱)可以反轉成url。

在模板中直接編寫簡單路由的 URL 鏈接不難,但對於包含可變部分的動態路由,在模板中構建正確的 URL 就很困難了。而且,直接編寫 URL 會對代碼中定義的路由產生不必要的依賴關系。如果重新定義路由,模板中的鏈接可能會失效。

為了避免這些問題,Flask 提供了 url_for() 輔助函數,它使用應用的 URL 映射中保存的信息生成 URL。

url_for() 函數最簡單的用法是以視圖函數名作為參數,返回對應的 URL。例如,在當前版本的 app.py 應用中調用 url_for('index') 得到的結果是 /,即應用的根 URL。調用 url_for('index', _external=True) 返回的則是絕對地址,在這個示例中是 http://localhost:5000/。

使用 url_for() 生成動態 URL 時,將動態部分作為關鍵字參數傳入。例如,url_for('user', name='john', _external=True) 的返回結果是 http://localhost:5000/user/john。

傳給 url_for() 的關鍵字參數不僅限於動態路由中的參數,非動態的參數也會添加到查詢字符串中。例如,url_for('user', name='john', page=2, version=1) 的返回結果是 /user/ john?page=2&version=1。

加載靜態文件

Web 應用不是僅由 Python 代碼和模板組成。多數應用還會使用靜態文件,例如模板中 HTML 代碼引用的圖像、JavaScript 源碼文件和 CSS。

在前一章中審查 app.py 應用的 URL 映射時,其中有一個 static 路由。這是 Flask 為了支持靜態文件而自動添加的,這個特殊路由的 URL 是 /static/ 。例如,調用 url_for('static', filename='css/styles.css', _external=True) 得到的結果是 http://localhost:5000/static/css/styles.css。

默認設置下,Flask 在應用根目錄中名為 static 的子目錄中尋找靜態文件。如果需要,可在 static 文件夾中使用子文件夾存放文件。服務器收到映射到 static 路由上的 URL 后,生成的響應包含文件系統中對應文件里的內容。

  1. 語法:url_for('static',filename='路徑')
  2. 可以加載css文件,可以加載js文件,還有image文件。

第一個:加載css文件

<link rel="stylesheet" href="{{ url_for('static',filename='css/index.css') }}"> 

第二個:加載js文件

<script src="{{ url_for('static',filename='js/index.js') }}"></script> 

第三個:加載圖片文件

<img src="{{ url_for('static',filename='images/zhiliao.png') }}" alt="">


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM