1. 模板簡介
模板是一個web開發中必備的模塊,因爲我們在渲染一個網頁的時候,並不只是渲染了一個純文本字符竄,而是渲染一個有富文本標籤的頁面,這個時候我們就需要用到模板了。在flask中,配套的模板是Jinja2
,Jinja2
的作者也是flask的作者。
2. flask中渲染模板
在flask中,如果我們需要渲染一個模板,那麼我們就需要用到render_template
這個方法了。
在我們新建一個flask項目的時候,會同時生成一個templates
的文件夾,然後我們就在裏面新建一個index.html
的文件。然後寫入測試代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>index</h1>
</body>
</html>
然後我們在app.py文件中寫一個視圖函數渲染我們的index.html
文件。
from flask import render_template
@app.route('/index/')
def index():
return render_template('index.html')
這樣,我們就成功的對html頁面進行了渲染。然後我們運行項目,輸入網址就能夠查看到效果了。
3. flask中模板文件查找路徑
在上面的render_template
函數中,爲什麼我們直接寫入index.html
,flask就會知道去templates
文件夾裏面去找這個文件呢。而不是去其他位置查找index.html
文件呢。這是因爲在flask中,默認的查找模板路勁就在項目的根目錄下面的templates
文件夾。所以當我們寫模板文件的時候,都會寫在templates
下面。
在flask中,我們也是可以修改模板的存放位置的,比如我們將模板文件存放位置修改爲E:\templates
,那麼我們就可以這樣寫。
from flask import Flask,render_template
app = Flask(__name__,template_folder=r'E:\templates')
這樣,flask每次查找模板文件路徑的時候,就回去這個文件夾下面尋找,如果沒有找到,就會報一個jinja2.exceptions.TemplateNotFound
的錯誤,所以,當我們遇到了這個錯誤的時候,我們就要知道是哪個位置出問題了。
4. 模板中傳入參數
在一個模板中,我們不可避免的會傳入一些參數,那麼在flask中,應該怎樣闖入參數呢。
首先編寫一個視圖,然後在render_template
中傳入一個關鍵字參數,例如下面的username=‘xxx’
from flask import render_template
@app.route('/index/')
def index():
return render_template('index.html',username='xxx')
然後我們在模板中怎樣使用這個變量呢?我們在index.html
中寫入以下代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>index</h1>
<p>userneme: {{ username }}</p>
</body>
</html>
所以,我們在模板中通過 {{ username }}
就可以拿到我們衝視圖中傳入的值了。也就是說,在Jinja2模板中,是通過{{ 變量名 }}
來獲取數據的,如果我們在{{ }}
中傳入了一個視圖並沒有穿給我們的變量,那麼也不會報錯,只是什麼都不顯示而已。
如果我們需要傳入多個參數,只需要依次在render_template
函數中傳入我們的關鍵之參數就可以了。
示例:
return render_template('index.html',username='xxx',age=18,...)
但是如果我們參數很多的話,那麼這樣我們也不方便我們管理和查看,這個時候我們就可以換一種方式了,定義一個字典,來存放所有的變量,然後在傳入模板中
示例:
@app.route('/index/')
def index():
context = {
'username':'xxx',
'age':18,
'height':180,
}
return render_template('index.html',context=context)
但是這個時候,當我們在模板找中直接輸入{{ username }},{{ age }}, {{ height }}
的時候,是獲取不到我們的數據的,因爲我們使用這種方法的話,在模板中,獲取參數就需要改變一下方式了。變成下面這樣.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>index</h1>
<p>userneme: {{ context.username }}</p>
<p>userneme: {{ context['age'] }}</p>
<p>userneme: {{ context.height }}</p>
</body>
</html>
在上面模板中,我們使用了兩種方式得到參數,context['username']
和context.username
。因爲context是一個字典,所以使用這兩種方法都是可以的。
但是這樣我們仍然覺得不方便,每次都需要通過context才能獲取到我們傳入的參數。那麼我們可不可以不通過context才能獲取參數呢,答案是可以的。
實例:
@app.route('/index/')
def index():
context = {
'username':'xxx',
'age':18,
'height':180,
}
return render_template('index.html',**context)
我們在視圖函數中這樣寫,我們就需要通過context才能得到我們的參數了。
**context
其實就是將這個字典打撒開來,形成關鍵字參數。所以,他和下面這種寫法是完全一樣的。
@app.route('/index/')
def index():
return render_template('index.html',username='xxx',age=18,height=180)
一般我們在項目的開發中,我們都是使用**context
這種寫法。
當然,在我們的實際開發中,傳送的數據肯定不是這麼簡單,一般都有數據嵌套之類的,還有對象。
例如下面這樣:
# 定義一個Person類
class Person():
def __init__(self,name,age):
self.name = name
self.age = age
person = Person('小明', 18) # 實例化一個Person對象
@app.route('/')
def index():
context = {
'username':'xujin',
'age':18,
'children':{
'name':'hah',
'height':190,
},
'person':person,
'list':[1,2,3]
}
return render_template('index.html',**context)
其實在Jinja2
模板中,我們對數據的操作和在python都是差不多的,像上面這種數據,我們就可以通過下面的方式來獲取。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>index</h1>
hello {{ username }}
<p> {{ children.name}} </p>
<p> {{ children['height'] }} </p>
{{ person }}
{{ person.name }}
{{ person.age }}
{{ list }}
{{ list[1] }}
</body>
</html>
5. url_for的使用
在模板中,我們一般也少不了需要url地址
,而我們直接手動寫入url地址
的話,不方便我們後面的管理,所以一般我們都會使用url_for
函數構造我們的url。
比如我們有一個login
頁面,然後我麼需要從首頁點擊登錄之後,就跳轉至login頁面,那麼我們需要這樣做。
@app.route('/login/')
def login():
return "這是login頁面"
@app.route('/index/')
def login():
return render_template('index.html')
然後我們在index.html
中寫入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>index</h1>
<p><a href="/login/">登陸</a></p>
<p><a href="{{ url_for('login') }}">登陸</a></p>
</body>
</html>
上面兩種方式一種是直接寫死url
的方式,一種就是使用url_for
的的方式。一般我們都是會使用url_for
這種方式的。
如果我們的url需要參數,那麼其實和在視圖中傳入參數是一樣的。
示例:
@app.route('/user/<int:user_id>/')
def user(user_id):
return "user id is %s " % user_id
模板文件中寫入
<a href="{{ url_for('user',user_id=1,next='xxx') }}">user</a>
<!-- 等價於下面這樣 -->
<a href="/user/1/?next=xxx">user</a>