中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

《Flask Web開發:基于Python的Web應用開發實戰》筆記二、

發布時間:2020-03-30 15:59:12 來源:網絡 閱讀:1368 作者:林樹楷 欄目:編程語言

第三章、模板

?視圖函數作用即生成請求的響應,如果把業務邏輯和表現邏輯混在一起會導致代碼難以理解和維護。吧表現邏輯轉移到模板中能夠提升程序的可維護性。
?模板是一個響應文本的文件,其中包含用占位變量表示的動態部分,其具體值只在請求的上下文才能知道。
?使用真實值替換變量,在返回最終得到的響應字符串,這一過程稱為渲染。

3.1、Jinja2模板引擎

3.1.1、渲染模板

?在默認情況下,Flask程序會在templates子文件夾中尋找模板。在下一個hello.py版本中,要把前面定義的模板保存在templates文件夾中,并分別命名為index.html和user.html。

from flask import Flask,render_template
from flask_script import Manager

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

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

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

if __name__ == "__main__":
   manager.run()
  • ?代碼詳解:Flask提供的render_template函數吧Jinja2模板引擎集成到程序中。render_template函數的第一個參數是模板的文件名,隨后的參數都是鍵值對,表示模板中變量對應的真實值。

3.1.2、變量

  • ?Jinja2能識別所有類型的變量,甚至是一些復雜的類型,例如列表、字典和對象。在模板中使用變量的一些示例如下:

    <p>DICT {{ mydict['key'] }}</p>
    <p>LIST {{ mylist[3] }}</p>
    <p>list with a variable index: {{ mylist[myintvar]}}</p>
    <p> object's method: {{ myobj.somemethod() }} </p>
  • 常用Jinja2 變量過濾器
  1. safe 渲染值時不轉義
  2. capitalize 把值的首字母轉換成大寫,其他字母轉換成小寫
  3. lower 把值轉換成小寫形式
  4. upper 把值轉換成大寫形式
  5. title 把值中每個單詞的首字母都轉換成大寫
  6. trim 把值的首尾空格去掉
  7. striptags 渲染之前把值中所有的HTML標簽都刪掉

3.1.3、控制結構

條件控制語句
{% if user %}
{% else %}
{% endif %}
for循環語句
{% for comment in comments %}
{% endfor %}
支持宏
{% marco render_comment(comment) %}
多處重復使用的模板代碼片段可以寫入單獨的文件,再包含在所有的模板中,以避免重復:
{ % include 'comment.html' %}

  • ?另外一中重復使用代碼的強大方式是模板繼承,他類似于Python代碼中的類繼承。繼承方式如下:首先創建一個名為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 bash.html %}
    {% block title %}
    Index
    {% endblock%}
    {% block head%}
    {{ super() }}
    <style>
    </style>
    {% endblock %}
    {% block body %}
    <h2>hello,world</h2>
    {% endblock %}
  • ?extends指令聲明這個模板衍生自base.htmk,在extends指令之后,基礎模板中的3個板塊重新定義,模板引擎會賈汪其插入適當的位置。注意新定義head塊,在基礎模板中內容是空的,所以使用super()獲取原來的內容。

3.2、使用Flask-Bootstrap集成Twitter Bootstrap

? Bootstrap是Twitter開發的一個開源框架,它提供的用戶界面組件可用于創建整潔且具有吸引力的網頁,并且這些網頁還能兼容所有現代的Web瀏覽器。
?Bootstrap是客戶端框架,不會直接涉及服務器。要下在程序中繼承Bootstrap,顯然需要對模板做所有必要的改動,更簡單的方法就是安裝Flask-Bootstrap的Flask擴展,簡化集成的過程。

  • Flask-Bootstrap使用pip方式安裝
    pip install flask-bootstrap
  • Flask擴展一般在創建程序實例時初始化。

    from flask.ext.bootstrap import Bootstrap
    bootstrap = Bootstrap(app)
  • 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">
    <h2>Hello, {{ name }}!</h2>
    </div>
    </div>
    {% endblock %}

代碼詳解:

  • ?Jinja2中的extends指令從Flask-Bootstrap中導入bootstrap/base.html,從而實現模板繼承。Flask-Bootstrap中的基礎模板提供了一個網頁框架,引入了Bootstrap中的所有CSS和JavaScript文件。
  • ? 基礎模板中定義了可在衍生模板中重新定義的塊。block和endblock指令定義塊中的內容可添加到基模板中。

Flaks-Bootstrap基模板中定義的塊:
塊名 說明

  1. doc 整個HTML文檔
  2. html_attribs <html>標簽的屬性
  3. html <html>標簽的內容
  4. head <head>標簽中的內容
  5. title <title>標簽中的內容
  6. metas 一組<meta>標簽
  7. styles 層疊樣式表定義
  8. body_attribs <body>標簽的屬性
  9. body <body>標簽中的內容
  10. navbar 用戶定義的導航條
  11. content 用戶定義的頁面內容
  12. scripts 文檔底部的JavaScript聲明

3.3、自定義錯誤頁面

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

  • 自定義錯誤頁面:
@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'),404

@app.errorhandler(500)
def internal_server_error(e):
    return render_templte('500.html'),500    
  • ? 和視圖函數一樣,錯誤處理程序也返回響應,它們還返回與該錯誤對應的數字狀態碼。
  • ? 如果從Github上克隆了這個程序的Git倉庫,執行git checkout 3c簽出這個程序的這個版本。

3.4、鏈接

?在模板中直接編寫簡單路由的URL連接不難,但對于包含可變部分的動態路由,在模板中構建正確的URL就很困難;并且直接編寫URL會對代碼中定義的路由產生不必要的依賴。
?Flask提供了url_for()輔助函數,可以使用程序URL映射中保存的信息生成URL。
?url_for()函數最簡單的用法是以視圖函數名(后者app.add_url_route()定義路由時使用的端點名)作為參數,返回對應的URL。
?使用url_for()生成動態地址時,將動態部分作為關鍵字參數傳入。例如,url_for('user',name='john',_external=True)的返回結果是http://localhost:5000/user/john
?傳入url_for()的關鍵字參數不僅限于動態路由中的參數。函數能將任何額外參數添加到查詢字符串中。例如,url_for('index',page=2)的返回結果是/?page=2

3.5、靜態文件

?默認設置下,Flask在程序根目錄中名為static的子目錄中尋找靜態文件。如果需要,可在static文件夾中使用子文件夾存放文件。

3.6、使用Flask-Monment本地化日期和時間

?問題背景:如果Web程序的用戶來自世界各地,那么處理日期和時間就不是一個簡單的任務。
?解決方法:通過使用JavaScript開發的優秀客戶端開源代碼庫,名為moment.js,可以在瀏覽器中渲染日期和時間。Flask-Monment是一個Flask程序擴展。能把moment.js集成到Jinja2模板中。

  • Flask-Moment可以通過pip安裝:

    pip install flask-moment
  • 初始化Flask-Moment:
    from flask.ext.moment import Moment
    moment = Moment(app)
  • 除了moment.js,Flask-Moment還依賴jquery.js.Bootstrap已經引入了jquery.js,因此只需引入moment.js即可。
    {% block scripts %}
    {{ super() }}
    {{ moment.include_moment() }}
    {% endblcok %}
  • 為了處理時間戳,Flask-Moment想模板開放了moment類,后臺可以將utc時間傳到前臺進行渲染。
    from datetime improt datetime
    @app.route('/')
    def index():
    return render_template('index.html',current_time=datetime.utcnow())
  • 在模板中渲染current_time
    <p>The local date and time is {{ moment(current_time).format('LLL) }}</p>
    <p>That was {{ moment(current_time).fromNow(refresh=True) }}</p>

更多moment.js用法:http://momentjs.com/docs/#/displaying/
Flask-Moment假定服務器端程序處理的時間是“純正的”datetime對象,且使用UTC表示。

第四章、Web表單

?對于一些重復操作(生成表單的HTML代碼和驗證提交的表單數據),Flask-WTF擴展可以把處理Web表單的過程變成一種愉悅的體驗。這個擴展對獨立的WTForms包進行了包裝,方便集成到Flask程序中。
WTForms官網:http://wtforms.simplecodes.com

  • Flask-WTF及其依賴可使用pip安裝:
    pip install flaks-wtf

4.1、跨站請求偽造保護

?默認情況,Flask-WTF能保護所有表單面授跨站請求偽造(CSRF)的***。為了實現CSRF保護,Flask-WTF需要程序設置一個密鑰。Flask-WTF使用這個密鑰生成加密令牌,再用令牌驗證請求中表單數據的真偽。

示例代碼(設置Flask-WTF):

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
  • ?代碼詳解:app.config字典可用來存儲框架、擴展和程序本身的配置變量
  • ?SECRET_KEY配置變量是通用密鑰,可在Flask和多個第三方擴展中使用。

4.2、表單類

使用Flask-WTF時,每個Web表單都由一個繼承自Form的類表示。

示例代碼(一個簡單的Web表單,包含一個文本字段和一個提交按鈕):

from flaks.ext.wtf import Form
from wtforms import StringField,SubmitField
from wtforms.validators import Required

class NameForm(Form):
    name = StringField("What's your name?",validators=[Required()])
    submit = SubmitField('Submit')
  • ?代碼詳解:StringField類表示屬性為type="text"的<input>元素;SubmitField類表示屬性為type="submit"的<input>元素。StringField構造函數中的可選參數validators指定一個由驗證函數組成的列表,在接收用戶提交的數據之前驗證數據。驗證函數Required()確保提交的字段不為空
  • ?Form基類由Flask-WTF擴展定義,從falsk.ext.wtf中導入。字段和驗證函數可以直接從WTForms包中導入。

WTForms支持的HTML標準字段

  1. StringField 文本字段
  2. TextAreaField 多行文本字段
  3. PasswordField 密碼文本字段
  4. HiddenField 隱藏文本字段
  5. DateField 文本字段,值為 datetime.date 格式
  6. DateTimeField 文本字段,值為 datetime.datetime 格式
  7. IntegerField 文本字段,值為整數
  8. DecimalField 文本字段,值為 decimal.Decimal
  9. FloatField 文本字段,值為浮點數
  10. BooleanField 復選框,值為 True 和 False
  11. RadioField 一組單選框
  12. SelectField 下拉列表
  13. SelectMultipleField 下拉列表,可選擇多個值
  14. FileField 文件上傳字段
  15. SubmitField 表單提交按鈕
  16. FormField 把表單作為字段嵌入另一個表單
  17. FieldList 一組指定類型的字段

WTForms驗證函數

  1. Email 驗證電子郵件地址
  2. EqualTo 比較兩個字段的值;常用于要求輸入兩次密碼進行確認的情況
  3. IPAddress 驗證 IPv4 網絡地址
  4. Length 驗證輸入字符串的長度
  5. NumberRange 驗證輸入的值在數字范圍內
  6. Optional 無輸入值時跳過其他驗證函數
  7. Required 確保字段中有數據
  8. Regexp 使用正則表達式驗證輸入值
  9. URL 驗證 URL
  10. AnyOf 確保輸入值在可選值列表中
  11. NoneOf 確保輸入值不在可選值列表中

4.3、把表單渲染成HTML

示例代碼:(使用Flask-WTF和Flask-Bootstrap渲染表單)

{% extends 'base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Flasky{% endblock %}

{% block page_content %}
<div class="page-header">
<h2>hello,{% if name %}{{ name }}{% else %}Stranger{% endif%}</h2>
</div>
{{ wtf.quick_form(form)}}
{% endblock %}
  • ? 代碼詳解:導入的bootstrap/wtf.html文件定義了一個使用Bootstrap渲染Flask-WTF表單對象的輔助函數。wtf.quick_form()函數的參數為Flask_WTF表單對象,使用Bootstrap的默認樣式渲染傳入表單。

4.4、在視圖函數中處理表單

示例代碼:(視圖函數index()不僅要渲染表單,還要接受表單中的數據。)

@app.route('/',methods=['GET','POST'])
def index():
    name = None
    form = NameForm()
    if form.validate_on_submit():
        name = form.name.data
        form.name.data = ''
    return render_template('index.html',form=form,name=name)    
  • 代碼詳解:app.route修飾器中添加的methods參數告訴Flask在URL映射中把這個視圖函數注冊為GET和POST請求的處理程序。如果沒指定methods參數,則默認把視圖函數注冊為GET請求的處理程序。
  • ?用戶提交表單后,服務器會收到一個POST請求。validate_on_submit()會調用name字段上附屬的Required()驗證函數。如果名字不為空,就能通過驗證,validate_on_submit()返回True。

4.5、重定向和用戶會話

?問題背景:當用戶輸入名字后提交表單,再點擊瀏覽器的刷新按鈕,會看到一個警告,關于要求再次提交表單之前進行確認。之所以會出這種問題,是因為刷新頁面時瀏覽器會重新發送之前已經發送過的最后一個請求。
?解決方案:使用重定向作為POST請求的響應,而不是使用常規響應。重定向是一種特殊的響應,響應內容是URL,而不是包含HTML代碼的字符串。瀏覽器收到這種響應,會向重定向的URL發起GET請求,顯示頁面的內容。
?另一問題:如果使用上面的解決方案,程序在處理POST請求時,使用from.name.data獲取用戶輸入的名字,一旦請求結束,數據也就丟失了。所以需要程序將數據存儲到用戶會話中,在請求之間“記住”數據。用戶是一種私有存儲,存在每個連接到服務器的客戶端中。

示例代碼:

from flask import Flask,render_template,session,redirect,url_for

@app.route('/',methods=['GET','POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        session['name'] = form.name.data
        return redirect(url_for('index'))
    return render_template('index.html',form=form,name=session.get('name')))    
  • ?代碼詳解:合法表單數據的請求最后會調用redirect()函數。redirect()是個輔助函數,用來生成HTTP重定向響應。redirect()函數參數是重定向的URL。url_for()生成URL,因為這個函數使用URL映射生成URL,從而保證URL和定義的路由兼容,并且修改路由名字后依然可用。

4.6、Flash消息

?問題背景:用戶提交了有一項錯誤的登錄表單,服務器發回的響應重新渲染了登錄表單,并在表單上面顯示信息,提示用戶名或密碼錯誤。

示例代碼:

from flask ipmort Flask,render_template,session,redirect,url_for,flash

@app.route('/',methods=['GET','POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        old_name = session.get('name')
        if old_name is not None and old_name != form.name.data:
            flash("Looks like you have changed your name")
       session['name'] = olde_name
       return redirect(url_for('index'))
   return render_template('index.html',name=session.get('name'),form=form)    ```

* ?代碼詳解:代碼會將每一次提交的名字與上一次**存儲在會話中的名字**進行比較,如果兩者不一樣則會發給客戶端下一個響應中顯示一個信息。
* ?僅調用flash()函數并不能把消息顯示出來,程序使用的模板要渲染這些信息,最好在基礎模板中渲染Flash消息,因為這樣所有頁面都能使用這些消息。Flask把**get_flashed_messages()函數**開放給模板,用來獲取并渲染消息。

{% block content %}
<div class="container">
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">
×
</button>
{{ message }}
</div>
{% endfor %}
{% block page_content %}
{% endblock %}
</div>
{% endblock %}

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

拉孜县| 尼玛县| 广东省| 台中县| 怀仁县| 泗阳县| 佳木斯市| 壶关县| 鄂伦春自治旗| 迁安市| 紫金县| 龙井市| 木兰县| 且末县| 旌德县| 延川县| 宝坻区| 吉安县| 峨眉山市| 青河县| 陇川县| 客服| 临安市| 监利县| 翁源县| 福清市| 祁门县| 鄂托克旗| 虹口区| 合水县| 江口县| 柘城县| 东平县| 玛纳斯县| 龙州县| 太和县| 舟曲县| 修武县| 环江| 永城市| 丰顺县|