Available variable declared in child template or in controller variables

I have a small mako template hierarchy that looks something like this:

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 

The problem is when I try to access the client index view that clientsindex.mako displays. I get an error message. AttributeError: Namespace 'self: /base.mako' has no member elements'.

What should be the right way to do this? I looked at the mako documentation and what I have found so far, I can use the module-level python block to declare the main actions, and then in base.mako just do self.attr.mainactions. The problem with this is inside this block. I do not have access to the request object.

I assume one more question: in my case I use functions as view-callables, but let me say that I wrote a separate clients.py view file that contains all the views related to clients. Is there a way to somehow configure the same controller context variables from the clients.py file? That way, I could have the mainactions variable set in the context of the template, no longer returning it in every dict view.

+4
source share
4 answers

This is a pretty old question, but here, I think it might do the trick. Keep in mind that when you write a template, you are actually showing the body() function by default.

I assume that mainactions is defined as a local variable for self.body() . But everything is cool, since we have access to ourselves ...

so instead of writing:

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

You should try to write:

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

However, this is not a very good way to achieve what you wanted to do. If I were you, I would do it with def or 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> 

The rest do not change ... the thing with def is that you simply override def from the parent, and then use def where you want in base.mako .

This is pretty much the case.

+1
source

Hmmm ... I haven’t written anything in pylons for ages, and I don’t have a pylon setting to test this. But try writing next.mainactions instead of self.mainactions and see what happens.

0
source

this answer is old, so I don’t know if you solved this problem.

One way that might work is to move your python block to view () def. Thus, this variable will actually be called in base.mako.

In my own application, I created a view object that contains a bunch of context variables that I need throughout my application, for example, view.page, view.perpage, etc. For each resolved view, I initiate this view (automatically compute context variables from get, post_data, route, etc.) and pass it as a context variable. That way, you can always pass view.mainactions, and you won't run any KeyErrors in your application, if by default you keep it None.

0
source

This answer to your "other question" :)

You can define your views as methods of the Controller class. Thus, you can convert the output of the Controller variable to a general method:

 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'}) 
0
source

Source: https://habr.com/ru/post/1346690/


All Articles