访问子模板中声明的变量或全局控制器变量
我有一组小的mako模板,结构大致是这样的:
base.mako
<h1>${self.view()}</h1>
${listactions(self.mainactions)}
${self.body()}
<%def name="listactions(actions)">
<ul>
% for action in actions:
<li>${action}</li>
% endfor
</ul>
</%def>
clientsbase.mako
<%inherit file="base.mako"/>
<%def name="view()">Clients</%def>
<%
mainactions = [request.route_url('clientsnew')]
%>
clientsindex.mako
<%inherit file="clientsbase.mako"/>
This is the index
问题是,当我尝试访问显示clientsindex.mako的客户索引视图时,我遇到了一个错误:AttributeError: Namespace 'self:/base.mako' has no member 'mainactions'。
那么,正确的做法应该是什么呢?我查阅了mako的文档,发现我可以使用一个模块级的python块来声明mainactions,然后在base.mako中使用self.attr.mainactions。但问题是,在这个块里我无法访问请求对象。
我想再问一个问题:在我的情况下,我使用函数作为视图调用,但假设我写了一个单独的clients.py视图文件,里面包含所有与客户相关的视图。有没有办法从clients.py文件中设置一些类似于控制器范围的上下文变量?这样我就可以在模板的上下文中提前设置一个mainactions变量,而不需要在每个视图的字典中返回它。
4 个回答
这个回答有点老了,所以我不知道你是否已经解决了这个问题。
一种可能有效的方法是把你的 Python 代码块放在 view() 函数里面。这样的话,那个变量就能在 base.mako 中被调用了。
在我自己的应用中,我创建了一个 view
对象,用来存放我在整个应用中需要的一些上下文变量,比如 view.page、view.perpage 等等。在每次调用视图的时候,我都会初始化这个 view
(自动从请求、提交的数据、路由等中计算出上下文变量),然后把它作为上下文变量传递出去。因此,你总是可以传递 view.mainactions,只要默认保持它为 None,你就不会在应用中遇到 KeyErrors 的问题。
嗯……我已经很久没用pylons写东西了,也没有安装pylons来检查这个问题。不过你可以试着把 self.mainactions
改成 next.mainactions
,看看会发生什么。
这是个比较老的问题,但我觉得这里的解释可能会有帮助。记住,当你写模板的时候,默认情况下其实是在显示一个叫 body()
的函数。
我猜 mainactions
是作为 self.body()
的一个局部变量被定义的。不过没关系,因为我们可以访问到 self……
所以,不要写:
mainactions = [request.route_url('clientsnew')]
你应该试着写:
self.mainactions = [request.route_url('clientsnew')]
不过,这样做其实并不是实现你想要的功能的好方法。如果我是你,我会用 def
或 block
来做。
在 base.mako
中:
<h1>${self.view()}</h1>
<%block name="mainaction">
</%block>
${self.body()}
<%def name="listactions(actions)">
<ul>
% for action in actions:
<li>${action}</li>
% endfor
</ul>
</%def>
在 clientbase.mako
中:
<%inherit file="base.mako"/>
<%def name="view()">Clients</%def>
<%block name="mainaction"
${request.route_url('clientsnew')}
</%block>
其他的部分没有变化……使用 def
的好处在于你可以覆盖父类中的 def
,然后在 base.mako
中使用你想要的 def
。
就这些了。