简体   繁体   English

在子模板或控制器范围的变量中声明的访问变量

[英]access variable declared in child template or controller-wide variables

I have a small hierarchy of mako templates that go something like: 我有一个小的mako模板层次结构,如下所示:

base.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 clientsbase.mako

<%inherit file="base.mako"/>
<%def name="view()">Clients</%def>
<%
    mainactions = [request.route_url('clientsnew')]
%>

clientsindex.mako clientsindex.mako

<%inherit file="clientsbase.mako"/>
This is the index

The problem is when I try to access the clients index view which renders clientsindex.mako I get the error AttributeError: Namespace 'self:/base.mako' has no member 'mainactions' . 问题是当我尝试访问客户端索引视图时呈现clientsindex.mako我得到错误AttributeError:命名空间'self:/base.mako'没有成员'mainactions'

What should be the proper way to do this? 应该怎样做才能做到这一点? I've gone through the mako documentation and what I've found so far is I can use a module-level python block to declare mainactions and then in base.mako just do self.attr.mainactions . 我已经浏览了mako文档,到目前为止我发现的是我可以使用模块级python块来声明mainactions,然后在base.mako中执行self.attr.mainactions The problem with that is inside this block I don't have access to the request object. 问题在于此块我无法访问请求对象。

I guess another question would be: in my case I'm using functions as view-callables, but let's say I've written a seperate clients.py view file which holds all the views related to clients. 我想另一个问题是:在我的情况下,我使用函数作为view-callables,但是假设我已经编写了一个单独的clients.py视图文件,其中包含与客户端相关的所有视图。 Is there a way to set sort of like controller-wide context variables from the clients.py file somehow? 有没有办法从clients.py文件中以某种方式设置类似控制器范围的上下文变量? This way I could have a mainactions variable set in the template's context already without returning it in each view's dict. 这样我就可以在模板的上下文中设置一个mainactions变量,而不必在每个视图的dict中返回它。

It's a quite old question but here, I guess it might do the trick. 这是一个相当古老的问题,但在这里,我想它可能会成功。 Keep in mind that when you're writing a template, you're actually displaying by default the function body() . 请记住,当您编写模板时,实际上您实际上是在显示函数body()

My guess is that mainactions is being defined as a local variable for the self.body() . 我的猜测是, mainactions被定义为self.body()的局部变量。 But everything is cool since we do have access to self... 但是一切都很酷,因为我们可以获得自我...

so instead of writing: 所以不要写:

mainactions = [request.route_url('clientsnew')]

You should try writing: 你应该尝试写:

self.mainactions = [request.route_url('clientsnew')]

That said, this is not really a good way to achieve what you wanted to do. 也就是说,这并不是实现您想要做的事情的好方法。 If I were you, i'd do it using def or block . 如果我是你,我会使用defblock来做。

base.mako 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 clientbase.mako

<%inherit file="base.mako"/>
<%def name="view()">Clients</%def>
<%block name="mainaction"
    ${request.route_url('clientsnew')}
</%block>

The remaining doesn't change...the thing with def is that you just overide the def from parent and then in the base.mako you use the def where you want. 剩下的不会改变... def的东西是你只是覆盖了父母的def ,然后在base.mako你使用你想要的def

That's pretty much it. 这就是它。

This answer is to your 'other question' :) 这个答案是你的“其他问题”:)

You can define your views as methods on a Controller class. 您可以将视图定义为Controller类上的方法。 This way you can factor the Controller-wide variable output into a common method: 这样,您可以将Controller范围的变量输出分解为常用方法:

from pyramid.view import view_config
from myproject.resources import MyResource


class MyController(object):

    def __init__(self, request):
        self.request = request

    def respond(self, additionalVars):
        additionalVars['myCommonVar1'] = 'common value'
        return additionalVars

    @view_config(
        context='myproject.resources:MyResource',
        request_method='GET',
        renderer='one.mak')
    def get_one(self):
        return self.respond({'var2':'sth'})

    @view_config(
        context='myproject.resources:MyResource',
        name = 'two',
        request_method='GET',
        renderer='two.mak')
    def get_two(self):
        return self.respond({'var3':'sth else'})

Hmmm... I have not written anything in pylons for ages nor do I have any pylons installation to check it. 嗯......我已经多年没有在挂架上写任何东西,也没有安装任何挂架来检查它。 But please try to write next.mainactions instead of self.mainactions and see what happens. 但请尝试编写next.mainactions而不是self.mainactions ,看看会发生什么。

this answer is old, so I don't know if you already solved this problem. 这个答案很老,所以我不知道你是否已经解决了这个问题。

One way that might work is moving your python block within the view() def. 一种可行的方法是在view()def中移动你的python块。 That way that variable will actually be called in base.mako. 这样,变量实际上将在base.mako中调用。

In my own app, I created a view object that holds a bunch of contextual variables that I need throughout my app, for example view.page, view.perpage, etc. On every view callable, I initiate this view (calculate contextual variables from gets, post_data, routes, etc. automatically) and pass it as a context variable. 在我自己的应用程序中,我创建了一个view对象,其中包含我在整个应用程序中需要的一组上下文变量,例如view.page,view.perpage等。在每个可调用的视图上,我启动此view (从中计算上下文变量)自动获取,post_data,路由等)并将其作为上下文变量传递。 Thus, you can always pass view.mainactions, and you won't run into any KeyErrors in your app as long as you keep it None by default. 因此,您始终可以传递view.mainactions,并且只要您将其保留为None,就不会遇到应用程序中的任何KeyErrors。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM