如何在Jinja模板有多个块时构建请求处理程序?

0 投票
1 回答
599 浏览
提问于 2025-04-18 14:58

我想做一个简单的网站,使用的是GAE框架/服务。这个网站很小,我其实不需要功能强大的Django框架,所以我选择了谷歌自己做的Webapp2框架,搭配Jinja2模板语言。

我之前主要用的是很基础的PHP和HTML,所以现在要适应真正的框架工作方式有点困难。我现在最大的疑问是,模板系统和请求处理器是如何协同工作的,特别是当页面的模板有几个“动态”元素时。

我先解释一下我在PHP中是怎么做的,这样你可能更容易理解我想实现的目标。

假设我想要一个网站,里面有:

  • 一个根据访问的页面而变化的标题,比如:“Mysite.com | 控制面板”
  • 一个动态的菜单栏,可能会根据用户的个人资料或登录状态而变化
  • 当然,页面的主体内容完全依赖于正在查看的页面

在PHP中,我会这样做,下面是一个简单的例子,index.php

<?php

/*here use the $_GET or $_POST variable, and the $_SESSION variable 
to figure out who's connected, which page is being displayed,
and store those values in global variables, for the 
included modules to use */

include('page_header.php'); // renders the whole <head> </head> tag and its content

echo "<body>";
include('views/menu.php'); //generates the menu, displays it

switch($page_name){
    case "home":
        include('home.php'); //renders the page body for the homepage
        break;

    case "articles":
        include('home.php'); //renders the page body for the blog articles listing
        break;

    case "guestbook":
        include('home.php'); //renders the page body for the guestbook
        break;


}
echo "</body>";

每个包含的模块都会使用调用它们的脚本(index.php)中的变量,以及$_POST、$_GET、$_SESSION这些超级全局变量,来决定显示什么内容,并将其渲染成HTML。在这里,index.php也做了一些非常基础的路由,使用了switch语句。

现在,回到webapp2和jinja2框架

我明白,要用Jinja以模块化的方式构建网页,需要使用块结构,并且要extend这些块。因此,为了构建一个类似于之前PHP例子的页面,我做了以下模板base.html

<html>
<head>
    <link rel="stylesheet" href="/static/css/reset.css">
    {% block title %}
    {% endblock title %}
</head>
<body>
    <div class="menu">
        {% block menu %}
        {% endblock menu %}
    </div>
    <div class="body">
        {% block content %}
        {% endblock content %}
    </div>
</body>
</html>

我不明白的是,如何构建不同的处理器,这些处理器又会生成Jinja用来渲染块的上下文,并且避免冗余

**另外,我可以使用多个不同的模板文件,它们单独只扩展一个块吗(例如:menu.html、header.html、body_home.html、body_articles.html等)**

你可以参考这个例子,这是一个小例子,几乎教会了我所有我需要知道的东西

感谢任何提供的帮助,抱歉语法错误,英语不是我的母语。

1 个回答

1

jinja2 中有个叫做 的功能,简单来说就是可以带参数的包含。

如果你需要带参数的包含,可以这样做:

{% macro menu(params) -%}
   do something
{%- endmacro %}

然后在你的模板中调用这个宏:

<div> menu('bar') </dib>

如果不需要提供参数,那就直接在父模板中写静态的 HTML 就可以了。

关于处理程序,你可以参考 App Engine 的 hello world 示例,只需用你的链接来加载 jinja 的环境。

我知道你想把 php 的例子翻译过来,但尽量把逻辑放在处理程序中,而不是模板里。

至于你的第二个问题,是的,如果你想的话,可以只扩展一个块,如果需要父模板的内容,可以用 {{super()}} 来获取。

撰写回答