- Python Falcon 教程
- Python Falcon - 首頁
- Python Falcon - 簡介
- Python Falcon - 環境搭建
- Python Falcon - WSGI 與 ASGI
- Python Falcon - Hello World (WSGI)
- Python Falcon - Waitress
- Python Falcon - ASGI
- Python Falcon - Uvicorn
- Python Falcon - API 測試工具
- 請求 & 響應
- Python Falcon - 資源類
- Python Falcon - 應用類
- Python Falcon - 路由
- Falcon - 字尾響應器
- Python Falcon - Inspect 模組
- Python Falcon - Jinja2 模板
- Python Falcon - Cookie
- Python Falcon - 狀態碼
- Python Falcon - 錯誤處理
- Python Falcon - Hook
- Python Falcon - 中介軟體
- Python Falcon - CORS
- Python Falcon - WebSocket
- Python Falcon - SQLAlchemy 模型
- Python Falcon - 測試
- Python Falcon - 部署
- Python Falcon 有用資源
- Python Falcon - 快速指南
- Python Falcon - 有用資源
- Python Falcon - 討論
Python Falcon - Jinja2 模板
Falcon 庫主要用於構建 API 和微服務。因此,預設情況下,Falcon 響應器返回 JSON 響應。但是,如果內容型別更改為 **falcon.MEDIA_HTML**,則可以渲染 HTML 輸出。
使用可變資料渲染 HTML 內容非常繁瑣。為此,使用 Web 模板庫。許多 Python Web 框架都捆綁了特定的模板庫。但 Falcon 作為一個極簡主義的微框架,並沒有預捆綁任何一個。
**Jinja2** 是許多 Python 框架使用的最流行的模板庫之一。在本節中,我們將瞭解如何在 Falcon 應用程式中使用 Jinja2。Jinja2 是一種快速且對設計人員友好的模板語言,易於配置和除錯。它的沙箱環境使其易於防止執行不受信任的程式碼,禁止潛在的不安全資料,並防止跨站點指令碼攻擊(稱為 **XSS 攻擊**)。
**Jinja2** 的另一個非常強大的功能是 **模板繼承**,您可以在其中定義一個具有通用設計特徵的基本模板,子模板可以覆蓋該模板。
首先,使用 PIP 工具在當前 Python 環境中安裝 **Jinja2**。
pip3 install jinja2
Hello World 模板
**Jinja2** 模組定義了一個 Template 類。透過讀取包含 HTML 指令碼(帶有 .html 副檔名)的檔案內容來獲得 Template 物件。透過呼叫此 Template 物件的 **render()** 方法,可以將 HTML 響應渲染到客戶端瀏覽器。Response 物件的 **content_type** 屬性必須設定為 **falcon.MEDIA_HTML**。
讓我們將以下 HTML 指令碼另存為應用程式資料夾中的 **hello.py**。
<html>
<body>
<h2>Hello World</h2>
</body>
</html>
示例
下面資源類中的 **on_get()** 響應器讀取此檔案並將其渲染為 HTML 響應。
import uvicorn
import falcon
import falcon.asgi
from jinja2 import Template
class HelloResource:
async def on_get(self, req, resp):
resp.status = falcon.HTTP_200
resp.content_type = 'text/html'
fp=open("hello.html","r")
tempobj=Template(fp.read())
resp.body=tempobj.render()
app = falcon.asgi.App()
hello = HelloResource()
app.add_route('/hello', hello)
if __name__ == "__main__":
uvicorn.run("hello:app", host="0.0.0.0", port=8000, reload=True)
輸出
執行上面的 Python 程式碼,並在瀏覽器中訪問 **https://:8000/hello** 連結。
模板變數
**Jinja2** 是一個伺服器端模板庫。網頁被構建為一個模板,透過在 HTML 指令碼內的適當分隔符內將 Jinja2 模板語言的各種元素作為佔位符。模板引擎讀取 HTML 指令碼,在伺服器上用上下文資料替換佔位符,重新組裝 HTML,並將其渲染到客戶端。
**Template.render()** 函式有一個可選的上下文字典引數。此字典的關鍵屬性成為模板變數。這有助於在網頁中渲染響應器傳遞的資料。
示例
在以下示例中,路由 ** /hello/nm** 與資源物件註冊,其中 nm 是路徑引數。**on_get()** 響應器將其作為上下文傳遞給從網頁獲得的模板物件。
import uvicorn
import falcon
import falcon.asgi
from jinja2 import Template
class HelloResource:
async def on_get(self, req, resp, nm):
resp.status = falcon.HTTP_200
resp.content_type = 'text/html'
fp=open("hello.html","r")
tempobj=Template(fp.read())
resp.body=tempobj.render({'name':nm})
app = falcon.asgi.App()
hello = HelloResource()
app.add_route('/hello/{nm}', hello)
if __name__ == "__main__":
uvicorn.run("hello:app", host="0.0.0.0", port=8000, reload=True)
**hello.html** 在模板變數名稱中讀取路徑引數。它充當 HTML 指令碼中的佔位符。它放在 **{{** 和 **}}** 符號中,以便其值顯示為 HTML 響應。
<html>
<body>
<h2>Hello {{ name }}</h2>
</body>
</html>
輸出
執行 Python 程式碼並輸入 **https://:8000/hello/Priya** 作為 URL。瀏覽器顯示以下輸出 -
Jinja2 模板中的迴圈
如果響應器傳遞任何 Python 可迭代物件,例如列表、元組或字典,則可以使用其迴圈構造語法在 Jinja2 模板中遍歷其元素。
{% for item in collection %}
HTML block
{% endfor %}
在以下示例中,**on_get()** 響應器將 students 物件(它是 **dict** 物件列表)傳送到模板 **list.html**。它依次遍歷資料並將其渲染為 HTML 表格。
import falcon
import json
from waitress import serve
from jinja2 import Template
students = [
{"id": 1, "name": "Ravi", "percent": 75.50},
{"id": 2, "name": "Mona", "percent": 80.00},
{"id": 3, "name": "Mathews", "percent": 65.25},
]
class StudentResource:
def on_get(self, req, resp):
resp.status = falcon.HTTP_OK
resp.content_type = falcon.MEDIA_HTML
fp=open("list.html","r")
tempobj=Template(fp.read())
resp.body=tempobj.render({'students':students})
**list.html** 是一個 Jinja2 模板。它接收 students 物件作為字典物件的列表,並將每個鍵的值放在表格的 <td>..<.td> 元素內。
<html>
<body>
<table border=1>
<thead> <tr>
<th>Student ID</th> <th>Student Name</th>
<th>percentage</th>
<th>Actions</th>
</tr> </thead>
<tbody>
{% for Student in students %}
<tr> <td>{{ Student.id }}</td> <td>{{ Student.name }}</td>
<td>{{ Student.percent }}</td>
<td>
<a href="#">Edit</a>
<a href="#">Delete</a>
</td> </tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
在瀏覽器的位址列中訪問 ** /students** 路由。學生列表將在瀏覽器中呈現。
HTML 表單模板
在本節中,我們將瞭解 Falcon 如何從 HTML 表單讀取資料。讓我們將以下 HTML 指令碼另存為 myform.html。我們將使用它來獲取 Template 物件並渲染它。
<html> <body> <form method="POST" action="https://:8000/students"> <p>Student Id: <input type="text" name="id"/> </p> <p>student Name: <input type="text" name="name"/> </p> <p>Percentage: <input type="text" name="percent"/> </p> <p><input type="submit"> </p> </body> </html>
Falcon App 物件在 Hello.py 檔案中宣告,該檔案還具有對映到 ** /adddnew** 路由的資源類。**on_get()** 響應器讀取 **myform.html** 並渲染相同的內容。將顯示 HTML 表單。表單透過 POST 方法提交到 ** /students** 路由。
為了能夠讀取表單資料,必須將 **falcon.RequestOptions** 類的 **auto_parse_form_urlencoded** 屬性設定為 True。
app = falcon.App() app.req_options.auto_parse_form_urlencoded = True
這裡,我們還從 **student.py** 匯入 **StudentResource** 類。**on_get()** 響應器呈現學生列表。
當用戶填寫並提交表單時,將呼叫 **on_post()** 響應器。此方法在 **req.params** 屬性中收集表單資料,這只是一個表單元素及其值的字典。然後追加 **students** 字典。
def on_post(self, req, resp): student=req.params students.append(student)
**hello.py** 的完整程式碼如下:
import falcon
import json
from waitress import serve
from jinja2 import Template
from student import StudentResource
class MyResource:
def on_get(self, req, resp):
resp.status = falcon.HTTP_200
resp.content_type = 'text/html'
fp=open("myform.html","r")
tempobj=Template(fp.read())
resp.body=tempobj.render()
app = falcon.App()
app.req_options.auto_parse_form_urlencoded = True
form = MyResource()
app.add_route('/addnew', form)
app.add_route("/students", StudentResource())
if __name__ == '__main__':
serve(app, host='0.0.0.0', port=8000)
包含 **StudentResource** 類以及 **on_get()** 和 **on_post()** 響應器的 student.py 如下:
import falcon
import json
from waitress import serve
from jinja2 import Template
students = [
{"id": 1, "name": "Ravi", "percent": 75.50},
{"id": 2, "name": "Mona", "percent": 80.00},
{"id": 3, "name": "Mathews", "percent": 65.25},
]
class StudentResource:
def on_get(self, req, resp):
resp.status = falcon.HTTP_OK
resp.content_type = falcon.MEDIA_HTML
fp=open("list.html","r")
tempobj=Template(fp.read())
resp.body=tempobj.render({'students':students})
def on_post(self, req, resp):
student = req.params
students.append(student)
resp.text = "Student added successfully."
resp.status = falcon.HTTP_OK
resp.content_type = falcon.MEDIA_JSON
從命令列執行 **hello.py**。透過輸入 **http://locLhost:8000/addnew** 在瀏覽器中開啟 HTML 表單。
**students** 資料庫字典將被追加。訪問 ** /students** 路由。您會發現添加了一行新資料。
多部分表單
為了讓使用者從本地檔案系統中選擇檔案,HTML 表單的 **enctype** 屬性必須設定為 multipart/form-data。Falcon 使用 **MultipartFormHandler** 處理 multipart/form-data 媒體型別,允許它遍歷表單中的主體部分。
**BodyPart** 類具有以下屬性:
**stream** - 僅適用於當前主體部分的流包裝器
**data** - 主體部分內容位元組
**content_type** 如果未指定,則預設為 text/plain,根據 RFC
**text** - 當前主體部分解碼為文字字串(僅在型別為 text/plain 時提供,否則為 None)
**media** - 透過媒體處理程式自動解析,方式與 req.media 相同
**name, filename** - 來自 Content-Disposition 標頭的相關部分
**secure_filename** - 可以安全地用於伺服器檔案系統的經過清理的檔名。
以下 HTML 指令碼(**index.html**)是一個多部分表單。
<html>
<body>
<form action="https://:8000/hello" method="POST" enctype="multipart/form-data">
<h3>Enter User name</h3>
<p><input type='text' name='name'/></p>
<h3>Enter address</h3>
<p><input type='text' name='addr'/></p>
<p><input type="file" name="file" /></p>
<p><input type='submit' value='submit'/></p>
</form>
</body>
</html>
此表單由下面程式碼中 **HelloResource** 類的 **on_get()** 響應器呈現。表單資料提交到 **on_post()** 方法,該方法遍歷各部分併發送表單資料的 JSON 響應。
import waitress
import falcon
import json
from jinja2 import Template
class HelloResource:
def on_get(self, req, resp):
resp.status = falcon.HTTP_200
resp.content_type = 'text/html'
fp=open("index.html","r")
tempobj=Template(fp.read())
resp.body=tempobj.render()
def on_post(self, req, resp):
result=[]
for part in req.media:
data={"name" :part.name,
"content type":part.content_type,
"value":part.text, "file":part.filename}
result.append(data)
resp.text = json.dumps(result)
resp.status = falcon.HTTP_OK
resp.content_type = falcon.MEDIA_JSON
app = falcon.App()
hello = HelloResource()
app.add_route('/hello', hello)
if __name__ == '__main__':
waitress.serve(app, host='0.0.0.0', port=8000)
執行上述程式並訪問 **https://:8000/hello** 連結以渲染表單,如下所示:
填寫資料並提交表單後,JSON 響應將在瀏覽器中呈現,如下所示:
[
{
"name": "name",
"content type": "text/plain",
"value": "SuyashKumar Khanna",
"file": null
},
{
"name": "addr",
"content type": "text/plain",
"value": "New Delhi",
"file": null
},
{
"name": "file",
"content type": "image/png",
"value": null,
"file": "hello.png"
}
]