如何将变量注入 TurboGears2 中装饰器用于模板的字典中?
当公开一个方法时,它可以返回模板使用的字典:
class RootController(TGController):
@expose('myapp.templates.index')
def index(self):
self.mykey = "foo"
self.mymenu = ["item1", "item2", "item3"]
self.selected = "item1"
return dict( mykey=self.mykey, mymenu=self.mymenu, selected=self.selected)
此代码工作正常。现在我想将菜单样板封装到这样的装饰器中:
class RootController(TGController):
@expose('myapp.templates.index')
@menu()
def index(self):
self.mykey = "foo"
self.mymenu = ["item1", "item2", "item3"]
self.selected = "item1"
return dict( mykey=self.mykey)
但我不知道如何编写这个菜单装饰器。如果我使用:
def before_render_cb(remainder, params, output):
return output.update( dict(mymenu=["item1", "item2", "item3"], selected="item1"))
class RootController(TGController):
@expose('myapp.templates.index')
@before_render(before_render_cb)
def index(self):
self.mykey = "foo"
self.mymenu = ["item1", "item2", "item3"]
self.selected = "item1"
return dict( mykey=self.mykey)
它将添加 mymenu 并选择到字典中,但我无权访问控制器的实例属性(self.mymenu 和 self.selected)
如果我使用装饰器:
class menus(object):
def __call__(self, func):
deco = Decoration.get_decoration(func)
return func
我可以访问装饰,但是不向暴露对象也不向控制器暴露。
我该怎么做?
When a method is exposed, it can return a dict used by a template :
class RootController(TGController):
@expose('myapp.templates.index')
def index(self):
self.mykey = "foo"
self.mymenu = ["item1", "item2", "item3"]
self.selected = "item1"
return dict( mykey=self.mykey, mymenu=self.mymenu, selected=self.selected)
This code works fine. Now I would like to encapsulate the menu boiler plate into a decorator like this :
class RootController(TGController):
@expose('myapp.templates.index')
@menu()
def index(self):
self.mykey = "foo"
self.mymenu = ["item1", "item2", "item3"]
self.selected = "item1"
return dict( mykey=self.mykey)
But I don't know how to write this menu decorator. If I use :
def before_render_cb(remainder, params, output):
return output.update( dict(mymenu=["item1", "item2", "item3"], selected="item1"))
class RootController(TGController):
@expose('myapp.templates.index')
@before_render(before_render_cb)
def index(self):
self.mykey = "foo"
self.mymenu = ["item1", "item2", "item3"]
self.selected = "item1"
return dict( mykey=self.mykey)
It will add mymenu and selected into the dict but I don't have access to the instance attribute of the controller (self.mymenu and self.selected)
If I use a decorator :
class menus(object):
def __call__(self, func):
deco = Decoration.get_decoration(func)
return func
I can have access to the decoration but not to the expose object neither to the controller.
How can I do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您始终可以使用 tg.request.controller_state.controller 和 tg.request.controller_state.method 访问处理当前请求的控制器对象和方法,
这应该可以实现从 @before_render 装饰器访问控制器变量。
请记住,不建议在控制器对象内设置变量,因为它在多个线程之间共享。建议的方法是使用 tg.tmpl_context 来存储特定于请求的临时变量。
您可能还有兴趣查看 tgext.menu 来生成应用程序菜单
You can always access the controller object and method that are handling the current request using
tg.request.controller_state.controller
andtg.request.controller_state.method
This should make possible to access the controller variables from the
@before_render
decorator.Keep in mind that setting variables inside the controller object is not suggested as it is shared between multiple threads. The suggested way to go is to use
tg.tmpl_context
to store temporary variables that are request specific.You might also be interested in giving a look at tgext.menu to generate application menus
这是我理解“before_render”装饰器的示例:
如您所见,“before_render”装饰器拦截发送的数据,对其进行处理并返回另一个数据。
“output”是“before_render”的局部变量。我们更改并更新了它的一致性,然后将其作为新数据发送。
Here is my example for understanding "before_render" decorator:
As You can see, "before_render" decorator intercepts sent data, works on it and returns another data.
"output" is a local variable for "before_render". We changed and updated it's consistence, then sent it as new data.