Python Pyramid - 模板



預設情況下,檢視函式響應的 content-type 為純文字。為了渲染 HTML,響應正文的文字可能包含 HTML 標籤,如下例所示:

示例

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response

def hello_world(request):
   return Response('<h1 style="text-align:center;">Hello World!</h1>')
   
if __name__ == '__main__':
   with Configurator() as config:
      config.add_route('hello', '/')
      config.add_view(hello_world, route_name='hello')
      app = config.make_wsgi_app()
   server = make_server('0.0.0.0', 6543, app)
   server.serve_forever()

輸出

啟動伺服器(執行上述程式碼)後,訪問https://:6543/,瀏覽器將呈現以下輸出:

Templates

然而,這種渲染 HTML 的方法,尤其是在可能包含某些變數資料的情況下,極其繁瑣。為此,Web 框架使用模板庫。模板庫將變數資料與其他靜態 HTML 程式碼合併,以動態生成和渲染網頁。

模板繫結

Pyramid 透過繫結到流行的模板庫(如 jinja2、Mako 和 Chameleon)來提供模板支援。

模板語言 Pyramid 繫結 預設副檔名
Chameleon pyramid_chameleon .pt, .txt
Jinja2 pyramid_jinja2 .jinja2
Mako pyramid_mako .mak, .mako

首先,我們需要安裝使用所需模板庫的相應 Python 庫。例如,要使用 jinja2 模板,請使用 PIP 安裝程式安裝pyramid_jinja2

pip3 install pyramid_jinja2

然後我們需要將其包含在應用程式配置中。

config.include('pyramid_jinja2')

pyramid.renderers 模組定義了 render_to_response() 函式。它與以下引數一起使用:

render_to_response(renderer_name, value, request)

renderer_name 是模板網頁,通常儲存在應用程式目錄的 templates 子資料夾中,value 引數是一個作為上下文傳遞給模板的字典,以及從 WSGI 環境獲得的請求物件。

將以下 HTML 指令碼另存為 templates 資料夾中的hello.jinja2

<html>
   <body>
      <h1>Hello, {{ name }}!</h1>
   </body>
</html>

Jinja2 模板庫

這裡,“name”是 jinja2 模板變數。jinja2 模板語言使用以下語法在 HTML 指令碼中插入變數和程式設計結構:

表示式

  • {{ ... }} 用於將表示式列印到模板輸出。

  • {% ... %} 用於語句。

  • {# ... #} 用於模板輸出中不包含的註釋。

條件語句

  • {% if expr %}

  • {% else %}

  • {% endif %}

迴圈

  • {% for var in iterable %}

  • {% endfor %}

在 hello.jinja2 {{ name }} 中,'name' 上下文變數的值在檢視響應中動態呈現。

渲染模板

hello_world() 檢視函式透過呼叫render_to_response() 函式直接渲染此模板。它還向模板傳送上下文值。

from pyramid.renderers import render_to_response

def hello_world(request):
   return render_to_response('templates/hello.jinja2',{'name':'Tutorialspoint'},
request=request)

示例

像往常一樣,此檢視新增到指向 / URL 的 hello 路由。完整的應用程式程式碼如下:

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.renderers import render_to_response

def hello_world(request):
   return render_to_response('templates/hello.jinja2', {'name':'Tutorialspoint'}, request=request)
   
if __name__ == '__main__':
   with Configurator() as config:
      config.add_route('hello', '/')
      config.include('pyramid_jinja2')
      config.add_view(hello_world, route_name='hello')
      app = config.make_wsgi_app()
   server = make_server('0.0.0.0', 6543, app)
   server.serve_forever()

輸出

執行伺服器並訪問https://:6543/。瀏覽器顯示以下結果:

HelloTP

每個檢視都必須返回一個響應物件。render_to_response() 函式是一個快捷函式,實際上返回一個響應物件。這允許上面的hello_world 檢視直接返回其對render_to_response() 的呼叫的結果。

另一方面,pyramid.renderers.render() 函式將模板渲染為字串。我們可以直接生成響應物件,並使用該字串作為響應的主體。

讓我們更改hello_world() 檢視函式如下:

from pyramid.renderers import render

def hello_world(request):
   retval = render('templates/hello.jinja2',
   {'name':'Tutorialspoint'}, request=request)
   return Response(retval)

其餘程式碼相同,瀏覽器也顯示與上述相同的輸出。

透過配置進行渲染

如前所述,Pyramid 的檢視可呼叫返回的 HTTP 響應的 content_type 為 text/plain。但是,如果@view_config 裝飾器的 renderer 引數被賦值為這些值中的任何一個,則可以將其更改為字串、JSON 或 JSONP。因此,Pyramid 具有以下內建渲染器:

  • JSON

  • 字串

  • JSONP

示例

在以下示例中,hello_world() 檢視函式配置為渲染 JSON 響應。

from pyramid.view import view_config

@view_config(route_name='hello',renderer='json')
def hello_world(request):
   return {'content':'Hello World!'}

輸出

將渲染器型別設定為 JSON 還會將 HTTP 響應的content_type 標頭設定為application/json。瀏覽器將顯示如下所示的 JSON 響應:

JSON

@view_config() 裝飾器的 renderer 引數可以設定為模板網頁(必須存在於 templates 資料夾中)。前提條件是必須安裝模板庫的相應 Python 繫結,並且應用程式配置必須包含該繫結。

我們已經安裝了 python_jinja2 包,因此我們可以使用 jinja2 模板由 hello_world() 檢視函式呈現,該函式由帶有 renderer 引數的 @view_config() 裝飾。

hello.jinja2 模板 HTML 程式碼如下:

<html>
   <body>
      <h1>Hello, {{ name }}!</h1>
   </body>
</html>

裝飾的 hello_world() 函式編寫如下:

from pyramid.view import view_config

@view_config(route_name='hello', renderer='templates/hello.jinja2')
def hello_world(request):
   return {'name':'Pyramid!'}

示例

在這種情況下,檢視函式返回一個字典物件。它作為上下文資料提供給模板,可以使用模板語言語法元素將其插入到 HTML 文字中。

渲染 jinja2 模板的完整程式碼如下:

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config

@view_config(route_name='hello', renderer='templates/hello.jinja2')
def hello_world(request):
   return {'name':'Pyramid!'}
   
if __name__ == '__main__':
   with Configurator() as config:
      config.include('pyramid_jinja2')
      config.add_route('hello', '/')
      config.scan()
      app = config.make_wsgi_app()
   server = make_server('0.0.0.0', 6543, app)
   server.serve_forever()

輸出

檢視函式提供的變數資料的模板網頁如下所示:

View

新增/更改渲染器

模板只不過是散佈著模板語言語法的網頁。即使 Pyramid 使用 jinja2 模板的預設副檔名“.jinja2”,但慣例是使用網頁的“.html”副檔名。

我們可以更改應用程式配置,以允許使用“.html”副檔名以及“.jinja2”。這是透過add_jinja2_renderer 完成的。

config.add_jinja2_renderer(".html")

hello.jinja2 模板現在重新命名為 hello.html。為了能夠使用此模板,讓我們將檢視函式定義更改為以下程式碼:

from pyramid.view import view_config

@view_config(route_name='hello', renderer='templates/hello.html')
def hello_world(request):
   return {'name':'Pyramid!'}

同時,我們透過新增“.html”渲染器來修改 Configurator 物件的屬性。

if __name__ == '__main__':
   with Configurator() as config:
      config.include('pyramid_jinja2')
      config.add_jinja2_renderer(".html")
      config.add_route(hello, '/')
      config.scan()
      app = config.make_wsgi_app()
   server = make_server('0.0.0.0', 6543, app)
   server.serve_forever()

來自 matchdict 的模板上下文

如前所述,如果路由配置中的 URL 模式包含一個或多個佔位符引數,則來自請求 URL 的值將與請求一起作為matchdict 物件傳遞,該物件又可以作為上下文資料傳遞給要呈現的模板。

對於我們的下一個示例,hello.html(jinja2 模板)保持不變。

<html>
   <body>
      <h1>Hello, {{ name }}!</h1>
   </body>
</html>

我們知道上下文變數“name”的值由檢視函式傳遞。但是,與其傳遞硬編碼值(如在前面的示例中),不如從matchict 物件中獲取其值。此物件由 URL 字串中的路徑引數填充。

from pyramid.view import view_config

@view_config(route_name='index', renderer='templates/hello.html')
def index(request):
   return {'name':request.matchdict['name']}

示例

修改後的應用程式程式碼如下:

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config

@view_config(route_name='index', renderer='templates/hello.html')
def index(request):
   return {'name':request.matchdict['name']}
if __name__ == '__main__':
   with Configurator() as config:
      config.include('pyramid_jinja2')
      config.add_jinja2_renderer(".html")
      config.add_route('index', '/{name}')
      config.scan()
      app = config.make_wsgi_app()
   server = make_server('0.0.0.0', 6543, app)
   server.serve_forever()

輸出

啟動伺服器,開啟瀏覽器並輸入 URL https://:6543/Tutorialspoint。尾隨字串成為matchdict 中“name”鍵的值。它被 jinja2 模板利用,並呈現以下輸出。

Jinja2

模板中的條件語句和迴圈

jinja2 模板語言允許在 HTML 指令碼中包含條件語句和迴圈結構。這些程式設計元素的 jinja2 語法如下:

條件語句

{% if expr %}
HTML
{% else %}
HTML
{% endif %}

迴圈

{% for var in iterable %}
HTML
{% endfor %}

可以看出,jinja2 語法與 Python 的 if 和 for 語句非常相似。不同的是,jinja2 不使用縮排來標記塊。相反,對於每個 if,都必須有一個 endif 語句。類似地,對於每個 for 語句,都必須有一個 endfor 語句。

示例

以下示例演示了模板條件語句和迴圈語句的使用。首先,Pyramid 程式碼使用 students 作為字典物件的列表,每個字典都具有學生的 id、姓名和百分比。此列表物件作為上下文傳遞給 marklist.html 模板

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config

students = [
   {"id": 1, "name": "Ravi", "percent": 75},
   {"id": 2, "name": "Mona", "percent": 80},
   {"id": 3, "name": "Mathews", "percent": 45},
]

@view_config(route_name='index', renderer='templates/marklist.html')

def index(request):
   return {'students':students}
if __name__ == '__main__':
   with Configurator() as config:
      config.include('pyramid_jinja2')
      config.add_jinja2_renderer(".html")
      config.add_route('index', '/')
      config.scan()
   app = config.make_wsgi_app()
   server = make_server('0.0.0.0', 6543, app)
   server.serve_forever()

將此程式儲存為 marklist.py。現在,以下 HTML 指令碼必須儲存為 marklist.html。它遍歷從檢視函式接收到的 students 列表物件,並以 HTML 表格的形式呈現學生資料。第四列使用 jinja2 if 語法顯示及格/不及格結果。

<html>
<body>
   <table border=1>
      <thead> 
         <tr>
            <th>Student ID</th> <th>Student Name</th>
            <th>percentage</th>
            <th>Result</th>
         </tr> 
      </thead>
      <tbody>
         {% for Student in students %}
            <tr> 
               <td>{{ Student.id }}</td> 
               <td>{{ Student.name }</td>
               <td>{{ Student.percent }}</td>
               <td>
                  {% if Student.percent>=50 %}
                  Pass
                  {% else %}
                  Fail
                  {% endif %}
               </td> 
            </tr>
         {% endfor %}
      </tbody>
   </table>
</body>
</html>

輸出

執行marklist.py 程式碼。https://:6543/連結呈現以下表格結果:

Marklist
廣告