日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

7、Flask实战第7天:Jinjia2模板

發布時間:2024/4/17 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 7、Flask实战第7天:Jinjia2模板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Jinja2模板介紹和查找路徑

在前面的章節中,視圖只是直接返回文本,然而在實際生產環境中其實很少這樣用,因為實際的頁面大多帶有樣式和復雜邏輯的HTML代碼,這可以讓瀏覽器其渲染出非常漂亮的頁面。

我們創建好flask項目,會發現有一個templates目錄,這個目錄就是用來存放模板文件

如果我們要使用模板,則需要導入render_template模塊

我們先在templates目錄下創建模板文件index.html,內容如下

<h3>I love python</h3>

然后我們來渲染使用這個模板

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

模板的路徑是相對于templates的,如果這個模板路徑是templates/posts/lists.html,那么路徑應該這樣寫:

render_template('posts/lists.html')

我們可以看看為什么flask如何把templates作為模板路徑的

按住ctrl,鼠標點擊app = Flask(__name__)中的Flask,可以發現這個類默認有個參數template_folder='templates'

因此,如果我們不想把templates作為模板目錄的話,比如用/home/heboan/haha這個目錄,我們可以這樣

app = Flask(__name__, template_folder='/home/heboan/haha')

?

模板傳參及其技巧

視圖函數如下,傳入參數username

@app.route('/') def index():return render_template('index.html', username='何波安')

模板文件index.html如下: 使用{{ 變量名 }}的方式引用

<body>姓名:{{ username }}</body>

如果傳入多個變量,可以這樣寫:

@app.route('/') def index():return render_template('index.html', username='何波安', age=18, job='coder')

但是當參數很多的時候,這樣就不方便了,我們可以用字典的方式來傳參

@app.route('/') def index():context = {'username': '何波安','age': 18,'job': 'coder'}return render_template('index.html', context=context)

這樣的話,我們模板就需要用context.username這種方式寫

<body>姓名:{{ context.username }} <br />年齡:{{ context.age }} <br />工作:{{ context.job }}</body>

如果我們想直接用username直接接收變量,我們可以這樣做:把字典當成關鍵字參數

@app.route('/') def index():context = {'username': '何波安','age': 18,'job': 'coder'}return render_template('index.html', **context)

這樣,我們就可以直接使用參數變量了

<body>姓名:{{ username }} <br />年齡:{{ age }} <br />工作:{{ job }}</body>

如果參數的值也是字典

@app.route('/') def index():context = {'username': '何波安','age': 18,'job': 'coder','attribute': {'height': '180cm','weight': '80kg'}}return render_template('index.html', **context)

那么模板可以這樣引用

<body>姓名:{{ username }} <br />年齡:{{ age }} <br />工作:{{ job }} <br />身高:{{ attribute.height }} <br />體重: {{ attribute.weight }}</body>

?

模板中使用url_for

模板里面有很多超鏈接,比如

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

模板index.html

<a href="/login/">登錄</a>

但是在實際開發中是不會寫死的,這樣不方便后期維護,這時候我們就可以用到url_for

<a href="{{ url_for('login') }}">登錄</a>

如果需要傳遞參數,如

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

模板index.html

<a href="{{ url_for('login', user_id='1') }}">登錄</a>

?

過濾器

過濾器是通過管道符號"|"進行使用的,例如: {{ name| length }},將返回name的長度。過濾器相當于是一個函數,把當前的變量傳入過濾器中,然后過濾器根據自己的功能,再返回相應的值,之后再將結果渲染到頁面中。

基本用法

@app.route('/') def index():return render_template('index.html', position=-2)

index.html

position的絕對值是: {{ position|abs }}

default過濾器

{{ <變量名>|default('默認值', boolean=True)}}

場景: 當用戶沒有自定義個性簽名的時候,使用default傳遞值,如下:

@app.route('/') def index():context = {'signature': '世界真的好贊'}return render_template('index.html', **context)

index.html

個性簽名: {{ signature|default('這個人真懶,什么都沒有留下~') }}

個性簽名字段signature存在,因此會顯示"世界真的好贊"

當沒有定義signature,則會顯示"這個人真懶,什么都沒有留下~"

@app.route('/') def index():context = {#'signature': '世界真的好贊' }return render_template('index.html', **context)

當定義signature為None時,看看如何顯示

@app.route('/') def index():context = {'signature': None}return render_template('index.html', **context)

我們發現,顯示的并不是default的值,而是None,這是為什么呢?

這是因為我們默認的default值只有變量不存在的時候才會引用,如果變量存在,那么就不會使用它

我們知道:None,空字符串,空字典,空列表等在布爾值都是False

如果我們想要在變量的布爾值是False的情況下就使用default的值,可以加上參數

個性簽名: {{ signature|default('這個人真懶,什么都沒有留下~', boolean=True) }}

還有一種簡寫方式

個性簽名: {{ signature or '這個人真懶,什么都沒有留下~' }}

?

escape字符轉義

看如下例子

@app.route('/') def index():context = {'signature': '<h1>世界真的好贊</h1>'}return render_template('index.html', **context)

index.html

個性簽名: {{ signature }}

我們發現jinjia2自動把signature當做普通字符串處理了(為了安全性)

我們可以關閉自動處理,在{% autoescape off %}里面的內容是不會被jinjia2模板自動處理的

{% autoescape off %}個性簽名: {{ signature }} {% endautoescape %}

還有另外一種方法就是使用safe

個性簽名: {{ signature| safe}}

在{% autoescape off %}里面的內容我們又想被轉義處理,就可以使用escape了

{% autoescape off%}個性簽名: {{ signature| escape}} {% endautoescape %}

last(value): 返回一個序列的最后一個元素。示例: names|last lenth(value): 返回一個序列或者字典的長度。 示例:names|lenth join(value, d=u''): 講一個序列用d這個參數的值拼接成字符串 int(value): 將值轉換為int類型 float(value): 將值轉換為float類型 lower(value): 將字符串轉換為小寫 upper(value):將字符串轉換為大寫 replace(value, old, new): 替換將old替換為new的字符串 truncate(value,length=255, killwords=False): 截取length長度的字符串 trim: 截取字符串前后的空白字符 string(value): 將變量轉換成字符串 wordcount(s): 計算一個長字符串中單詞的個數 其他常用的過濾器

?

自定義過濾器

自定義過濾器其實就是定義函數,比如我要定義一個cut過濾器,這個過濾器實現的功能是把變量值里面的hello全部去掉

@app.route('/') def index():context = {'article': 'hello, this is test hello world'}return render_template('index.html', **context)@app.template_filter('cut') #把cut函數注冊到過濾器中 def cut(value): #value就是使用過濾器的變量value = value.replace('hello', '')return value #函數的返回值會作為過濾器的返回值

index.html

{{ article|cut }}

?

自定義事件處理過濾器案例

在實際案例中,我們會看到這種情況,顯示內容發表的時間,比如微信。現在我們來自定義一個過濾器來實現這樣的需求:

發表時間距離現在的時間間隔:

  1、如果時間間隔在1分鐘以內,顯示‘剛剛’
  2、如果大于1分鐘小于1小時,顯示‘xx分鐘前’
  3、如果大于1小時小于24小時,顯示‘xx小時前’
  4、如果大于24小時小于30天,顯示‘xxx天前’
  5、否則顯示具體時間: 如2018/6/30 14:45

@app.route('/') def index():context = {'create_time': datetime(2018,6,30,12,0,0)}return render_template('index.html', **context)@app.template_filter('handle_time') def handle_time(time):if isinstance(time, datetime):now = datetime.now()timestamp = (now - time).total_seconds()if timestamp < 60:return '剛剛'elif timestamp >= 60 and timestamp < 60*60:minutes = timestamp / 60return '{}分鐘前'.format(minutes)elif timestamp >= 60*60 and timestamp <60*60*24:hours = timestamp / (60*60)return '{}小時前'.format(int(hours))elif timestamp >= 60*60*24 and timestamp < 60*60*30:days = timestamp / (60*60*24)return '{}天前'.format(int(days))else:return time.strftime('%Y/%m/%d %H:%M')else:return time

index.html

{{ create_time|handle_time }}

?

if和for語句

if語句

{% if score >= 90 %}<p>優秀</p> {% elif score >= 80 %}<p>良好</p> {% elif score >= 60 %}<p>及格</p> {% else %}<p>不及格</p> {% endif %}

for語句

<!--普通的遍歷--> <url>{% for user in users %}<li> {{ user.name }} </li>{% endfor %} </ul><!--含else的for--> <url>{% for user in users %}<li> {{ user.name }} </li>{% else %}<li> user not found </li>{% endfor %} </ul><!--字典遍歷--> <ul>{% for key,value in users.items() %}<dt> {{ key }} </dt><dd> {{value}} <dd>{% endfor %} </ul>

jinjia2中還包含以下變量,可以獲取當前遍歷的狀態

變量描述
loop.index當前迭代的索引(從1開始)
loop.index0當前迭代的索引(從0開始)
loop.first是否是第一次迭代,返回True或False
loop.last是否是最后一次迭代,返回True或False
loop.length序列的長度

注意:不可以使用continue和break表達式來控制循環的執行

?

模板中的宏跟Python中的函數類似,可以傳遞參數,但是不能有返回值,可以將一些經常用到的代碼片段放到宏中,然后把一些不固定的值抽取出來當成一個變量

index.html

<!--定義宏--> {% macro input(name, value='', type='text') %}<input name="{{ name }}" value="{{ value }}" type="{{ type }}" /> {% endmacro %}<!--使用宏--> 用戶名: {{ input('username') }} <br /> 密碼: {{ input('password', type='password') }}

上面我們把宏定義在模板文件index.html里面,但是在實際開發當中我們會把它單獨放到一個文件中

我們可以在templates下面創建一個目錄macros,在macros目錄下面創建文件macros.html文件,這個文件來寫宏

然后我們在index.html中如要使用宏就需要導入

{% from 'macros/macros.html' import input %} 用戶名: {{ input('username') }} <br /> 密碼: {{ input('password', type='password') }}

或者這樣

{% import 'macros/macros.html' as macros %} 用戶名: {{ macros.input('username') }} <br /> 密碼: {{ macros.input('password', type='password') }}

還有一個問題就是:宏文件里面能夠直接獲取到服務器傳遞過來的值嗎?

@app.route('/') def index():context = {'str1': 'hello'}return render_template('index.html', **context)

macros/macros.html

{% macro input(name, value='', type='text') %}<input name="{{ name }}" value="{{ str1 }}" type="{{ type }}" /> {% endmacro %

很顯然并沒有獲取到,如果我們想模板文件中能夠獲取到,需要在導入模塊的時候這樣寫:

{% import 'macros/macros.html' as macros with context%} 用戶名: {{ macros.input('username') }} <br /> 密碼: {{ macros.input('password', type='password') }}

?

set和with定義模板變量

在模板中也可以定義變量

set

使用set定義變量,后面開始就可以引用此變量

index.html

{% set name = 'heboan' %} <h1>{{ name }}</h1>

with

使用with定義變量,只能在with代碼塊里面才能引用

index.html

{% with name = 'heboan' %}<h1>{{ name }}</h1> {% endwith %}

我們也可以把set包含在with里面,這樣的話set定義的變量也只能在with代碼塊里面生效

{% with name = 'heboan' %}{% set age = 18 %}<h1>{{ name }}</h1> <h2>{{ age }}</h2> {% endwith %}

?

加載靜態文件

建好flask項目后,和templates一樣 ,flask自動為我們建立了一個目錄static,這個目錄是用來存放靜態文件的,比如css、js、圖片等。

當然,靜態文件目錄的位置也是可以修改的

按住ctrl點擊 app = Flask(__name__)中的Flask,可以看到默認有一個參數是static_folder='static'

如果我們想改的話,可以這樣

app = Flask(__name__, static_floder='<path>')

這里,我以圖片來說明如何加載靜態文件,至于css、js都是一樣的操作

主要還是用到url_for()

我們現在static下創建以個目錄images,然后在該目錄存放一張圖片mm.jpg

index.html

<img src="{{ url_for('static', filename='images/mm.jpg') }}">

?

include

include的作用就是在一個模板中可以包含其他額模板

比如一個頁面,頂部和底部是一樣的,只有中間的板塊不一樣,這樣的話,我們就可以創建2個公共的模板。然后在其他的模板中把他們include進來即可

在templates創建一個目錄common,在common創建兩個模板header.html和footer.html

header.html

<div><p>這是頭部</p> </div>

footer.html

<div><p>這是底部</p> </div>

在index.html中include

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body>{% include 'common/header.html' %}<div><p>---這是中間的內容---</p></div>{% include 'common/footer.html' %}</body> </html>

?

模板繼承

前面我們使用了include把其他模板的內容包含進來,從而減少代碼量。然而這并不是最好的方案。我們還可以使用模板繼承

我們在templates目錄下創建一個模板文件base.html

我們在模板里面把會變動的地方使用{% block <name> %} {% endblock %}并取一個名字就可以了

然后我們在indext.html來繼承base.html

現在訪問首頁

轉載于:https://www.cnblogs.com/sellsa/p/9244723.html

總結

以上是生活随笔為你收集整理的7、Flask实战第7天:Jinjia2模板的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。