Python Falcon Jinja2模板
Falcon库主要用于构建API和微服务。因此,默认情况下,Falcon响应器会返回一个JSON响应。然而,如果将内容类型改为 falcon.MEDIA_HTML,就 有可能渲染HTML输出。
渲染带有可变数据的HTML内容是非常繁琐的。为了这个目的,可以使用网络模板库。许多Python网络框架都捆绑了特定的模板库。但是Falcon作为一个极简的微型框架并没有预先捆绑任何人。
Jinja2 是最流行的模板库之一,被许多Python框架使用。在本节中,我们将看到如何在Falcon应用程序中使用inja2。jinja2是一种快速且对设计师友好的模板语言,易于配置和调试。它的沙盒环境使它很容易防止执行不受信任的代码,禁止潜在的不安全数据,并防止跨站脚本攻击(称为 XSS攻击 )。
jinja2 的另一个非常强大的功能是 模板继承 ,在这里你可以定义一个具有共同设计特征的基础模板,子模板可以覆盖。
首先,使用PIP工具在当前的Python环境中安装 jinja2 。
pip3 install jinja2
Hello World模板
jinja2 模块定义了一个Template类。Template对象是通过读取包含HTML脚本的文件内容(扩展名为.html的文件)获得的。通过调用这个模板对象的 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代码并在浏览器中访问 http://localhost:8000/hello 。
模板变量
jinja2 是一个服务器端的模板库。网页是以模板的形式构建的,它将jinja2模板语言的各种元素作为占位符放在HTML脚本中适当的分隔符中。模板引擎读取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代码并输入 http://localhost:8000/hello/Priya 作为 URL。浏览器显示以下输出 –
jinja2模板的循环
如果响应者传递任何Python可迭代对象,如列表、元组或字典,其元素可以在jinja2模板内使用其循环结构语法进行遍历。
{% for item in collection %}
HTML block
{% endfor %}
在下面的例子中, on_get() 响应器发送学生对象,这是一个 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模板。它接收学生对象作为字典对象的列表,并将每个键的值放在一个表格的
<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。我们将用它来获取模板对象并渲染它。
<html>
<body>
<form method="POST" action="http://localhost: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
在这里,我们也从stud ent.py 导入 StudentResource 类 。 on_get() 响应器渲染了学生的列表。
当用户填写并提交表单时, on_post() 响应器将被调用。这个方法在 req.params 属性中收集表单数据,它只不过是一个表单元素及其值的字典。然后, 学生 字典被追加。
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 路线。你会发现一个新的行被追加。
多部分表格
为了让用户从本地文件系统中选择文件,HTML表单的 enctype 属性必须被设置为multipart/form-data。Falcon使用 MultipartFormHandler 来处理multipart/form-data媒体类型,允许它遍历表单中的主体部分。
BodyPart 类有以下属性—
- stream – 当前身体部分的流包装器
-
data – 身体部分的内容字节
-
content_type 如果没有指定,将默认为text/plain,按照RFC的规定。
-
text – 当前身体部分被解码为文本字符串(只有在它是text/plain类型的情况下,否则就没有)。
-
media – 由媒体处理程序以与req.media相同的方式自动解析的。
-
name, filename – 来自Content-Disposition标头的相关部分
-
secure_filename – 经过消毒的文件名,可以在服务器文件系统中安全使用。
下面的HTML脚本( index.html )是一个多部分的形式。
<html>
<body>
<form action="http://localhost: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)
Run the above program and visit http://localhost:8000/hello link to render the form as shown below −
当填写完数据后提交表单时,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"
}
]
Python Falcon教程
- Python Falcon教程
- Python Falcon 简介
- Python Falcon 环境搭建
- Python Falcon WSGI vs ASGI
- Python Falcon Hello World(WSGI)
- Python Falcon Waitress
- Python Falcon ASGI
- Python Falcon Uvicorn
- Python Falcon API测试工具
- Python Falcon 请求与响应
- Python Falcon 资源类
- Python Falcon App类
- Python Falcon 路由
- Python Falcon 后缀的响应器
- Python Falcon inspect模块
- Python Falcon Jinja2模板
- Python Falcon Cookies
- Python Falcon 状态代码
- Python Falcon 错误处理
- Python Falcon 钩子
- Python Falcon 中间件
- Python Falcon CORS
- Python Falcon Websocket
- Python Falcon SQLAlchemy模型
- Python Falcon 测试
- Python Falcon 部署