0

当一个方法被暴露时,它可以返回一个模板使用的字典:

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 并选择到 dict 但我无权访问控制器的实例属性(self.mymenu 和 self.selected)

如果我使用装饰器:

class menus(object):
    def __call__(self, func):
        deco = Decoration.get_decoration(func)
        return func

我可以访问装饰,但不能访问控制器也不能访问对象。

我怎样才能做到这一点?

4

2 回答 2

1

您始终可以使用和访问处理当前请求的控制器对象和tg.request.controller_state.controller方法tg.request.controller_state.method

这应该可以从@before_render装饰器访问控制器变量。

请记住,不建议在控制器对象内设置变量,因为它在多个线程之间共享。建议的方法是使用tg.tmpl_context存储特定于请求的临时变量。

您可能也有兴趣查看tgext.menu以生成应用程序菜单

于 2012-03-14T22:02:19.323 回答
0

这是我理解“before_render”装饰器的示例:

#---=== read this section second: ===---

def make_menu_from_controller(remainder, params, output):
    controller = output.pop('controller') #Here we remove RootController sent by "index" and write it to "controller" variable.
                                          #Only {'page':'index'} left inside "output" variable
    return output.update(dict(mykey=controller.mykey, mymenu=controller.mymenu, selected=controller.selected)) #here we update dict adding "mykey", "mymenu" and "selected" keys. 

#---=== read this section first: ===---

class RootController(TGController):

    def __init__(self): #here we initiate variables, which are not changed during surfing
        self.mykey = "foo"
        self.mymenu = ["item1", "item2", "item3"]

    @expose('myapp.templates.index')
    @before_render(make_menu_from_controller)
    def index(self):
        self.selected = "item1"
        return dict(page='index', controller=self) #RootController sends itself

如您所见,“before_render”装饰器拦截发送的数据,对其进行处理并返回另一个数据。“output”是“before_render”的局部变量。我们更改并更新了它的一致性,然后将其作为新数据发送。

于 2012-03-03T12:35:52.803 回答