Flask框架基礎(二)

1 程序的基本結構

1.1初始化

所有Flask 程序都必須創建一個程序實例。Web 服務器使用一種名爲Web 服務器網關接口(Web Server Gateway Interface,WSGI)的協議,把接收自客戶端的所有請求都轉交給這個對象處理。程序實例是Flask 類的對象。

from flask import Flask
app = Flask(__name__)

傳入Flask構造方法的第一個參數是模塊或者包的名稱,我們應該使用特殊變量 __name __。
Python會根據所處的模塊來賦予 __ name __變量相應的值,對於我們程序來說,這個值爲app

1.2註冊路由

客戶端(例如Web 瀏覽器)把請求發送給Web 服務器,Web 服務器再把請求發送給Flask
程序實例。程序實例需要知道對每個URL 請求運行哪些代碼,所以保存了一個URL 到Python 函數的映射關係。處理URL 和函數之間關係的程序稱爲路由。

@app.route('/')
def index():
return '<h1>Hello World!</h1>'

在這個程序中,app.route()裝飾器把根地址/和index()函數綁定起來,當用戶訪問這個URL時就會觸發index()函數。視圖函數index()返回 " Hello World! "

route()裝飾器的第一個參數是URL規則,用字符串表示,必須以/開始。這裏的URL是相對的URL(又稱內部URL),即不包含域名的URL,以域名www.google.com爲例,“/”對應的是根地址,即www.google.com,如果把URL規則改爲“/maps”,則實際的絕對地址爲www.google.com/maps

動態路由

如果你仔細觀察日常所用服務的某些URL 格式,會發現很多地址中都包含可變部分。例如, 你的Facebook 資料頁面的地址是http://www.facebook.com/&lt;your-name>, 用戶名(your-name)是地址的一部分。Flask 支持這種形式的URL,只需在route 修飾器中使用特殊的句法即可。下例定義的路由中就有一部分是動態名字:

@app.route('/user/<name>')
def user(name):
return '<h1>Hello, %s!</h1>' % name

1.3啓動服務器

程序實例用run 方法啓動Flask 集成的開發Web 服務器:

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

name__==' main__'是Python 的慣常用法,在這裏確保直接執行這個腳本時才啓動開發Web 服務器。如果這個腳本由其他腳本引入,程序假定父級腳本會啓動不同的服務器,因此不會執行app.run()。

1.4完整的程序

示例1.4 hello.py:一個完整的Flask 程序
from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return '<h1>Hello World!</h1>'

@app.route('/user/<name>')
def user(name):
    return '<h1>Hello, %s!</h1>' % name

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

1.4 異常捕獲

使用裝飾器的形式去捕獲指定的錯誤碼和異常

@app.errorhandler(404)
def page_not_found(error):
    return    '404'

1.5請求鉤子

爲了讓每個視圖函數避免編寫重複功能的代碼,Flask提供了通用設施的功能,即請求鉤子。
請求鉤子是通過裝飾器的形式實現,Flask支持如下四種請求鉤子:

  • before_first_request:註冊一個函數,在處理第一個請求之前運行。
  • before_request:註冊一個函數,在每次請求之前運行。
  • after_request:註冊一個函數,如果沒有未處理的異常拋出,在每次請求之後運行。
  • teardown_request:註冊一個函數,即使有未處理的異常拋出,也在每次請求之後運行。

--

2 模板

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

2.1 Jinja2模板引擎

  1. Jinjia2是由python實現的
  2. 是Flask內置的模板語言
  3. 參照Django設計思想設計的,跟Django差不多

2.1.1渲染模板

默認情況下,Flask 在程序文件夾中的templates 子文件夾中尋找模板。Flask提供的

示例 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)

示例 templates/index.html:Jinja2 模板

<h1>Hello World!</h1>

示例

<h1>Hello, {{ name }}!</h1>

render_template 函數封裝了該模板引擎
render_template 函數的第一個參數是模板的文件名,後面的參數都是鍵值對,表示模板中變量對應的真實值

2.1.2 變量

在模板中使用的{{ name }} 結構表示一個變量,它是一種特殊的佔位符,告訴模
板引擎這個位置的值從渲染模板時使用的數據中獲取。

可以使用過濾器修改變量,過濾器名添加在變量名之後,中間使用豎線分隔。例如,下述模板以首字母大寫形式顯示變量name 的值:

Hello, {{ name|capitalize }}

Jinja2 提供的部分常用過濾器

表 Jinja2變量過濾器

過濾器名 說明
safe 渲染值時不轉義
capitalize 把值的首字母轉換成大寫,其他字母轉換成小寫
lower 把值轉換成小寫形式
upper 把值轉換成大寫形式
title 把值中每個單詞的首字母都轉換成大寫
trim 把值的首尾空格去掉
striptags 渲染之前把值中所有的HTML 標籤都刪掉

2.1.3 控制結構

Jinja2 提供了多種控制結構,可用來改變模板的渲染流程。

  • 條件控制:
{% 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>

模板代碼複用

在模板中,可能會遇到以下問題

  1. 多個模板具有完全相同的頂部和底部內容
  2. 多個模板中具有相同的模板代碼內容,但是內容中部分值不一樣
  3. 多個模板中具有完全相同的 html 代碼塊內容

像遇到這種情況,可以使用 JinJa2 模板中的 宏、繼承、包含來進行實現

模板繼承

標籤定義的內容

{% block %} {% endblock %}

模板繼承是爲了重用模板中的公共內容。一般Web開發中,繼承主要使用在網站的頂部菜單、底部。這些內容可以定義在父模板中,子模板直接繼承,而不需要重複書寫。

首先創建一個名爲base.html 的基模板
<html>
<head>
    {% block head %}
    <title>{% block title %}{% endblock %} - My Application</title>
    {% endblock %}
</head>
<body>
    {% block body %}
    {% endblock %}
</body>
</html>

block 標籤定義的元素可在衍生模板中修改。在本例中,我們定義了名爲head、title 和
body 的塊。注意,title 包含在head 中。下面這個示例是基模板的衍生模板:

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

extends 指令聲明這個模板衍生自base.html。在extends 指令之後,基模板中的3 個塊被
重新定義,模板引擎會將其插入適當的位置。注意新定義的head 塊,在基模板中其內容不
是空的,所以使用super() 獲取原來的內容。

2.2 Flask-Bootstrap

Bootstrap(http://getbootstrap.com/)是Twitter 開發的一個開源框架,它提供的用戶界面組
件可用於創建整潔且具有吸引力的網頁,而且這些網頁還能兼容所有現代Web 瀏覽器。
Bootstrap 是客戶端框架,因此不會直接涉及服務器。服務器需要做的只是提供引用了
Bootstrap 層疊樣式表(CSS) 和JavaScript 文件的HTML 響應, 並在HTML、CSS 和
JavaScript 代碼中實例化所需組件。這些操作最理想的執行場所就是模板。

  • 初始化Flask-Bootstrap
from flask.ext.bootstrap import Bootstrap
# ...
bootstrap = Bootstrap(app)

初始化 Flask-Bootstrap 之後,就可以在程序中使用一個包含所有 Bootstrap 文件的基模板。這個模板利用Jinja2的模板繼承機制,讓程序擴展一個具有基本頁面結構的基模板,其中就有用來引入 Bootstrap 的元素。官方教程

{% extends "bootstrap/base.html" %}<!--extends 指 令 從 Flask-Bootstrap中導入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 %}

2.3 自定義錯誤頁面

像常規路由一樣,Flask 允許程序使用基於模板的自定義錯誤頁面。最常見的錯誤代碼有
兩個:404,客戶端請求未知頁面或路由時顯示;500,有未處理的異常時顯示。

例 hello.py:自定義錯誤頁面

@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

2.4 鏈接

在模板中直接編寫簡單路由的 URL 鏈接不難,但對於包含可變部分的動態路由,在模板中構建正確的 URL 就很困難。而且,直接編寫 URL 會對代碼中定義的路由產生不必要的依賴關係。如果重新定義路由,模板中的鏈接可能會失效。Flask 提供了 url_for() 輔助函數,它可以使用程序 URL 映射中保存的信息生成 URL。

2.5 靜態文件

用靜態文件,例如 HTML代碼中引用的圖片、JavaScript 源碼文件和 CSS。默認設置下,Flask 在程序根目錄中名爲 static 的子目錄中尋找靜態文件。如果需要,可在static 文件夾中使用子文件夾存放文件。
如索引圖標的位置{{ url_for('static', filename = 'favicon.ico') }}
flask

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章