如何将变量注入 TurboGears2 中装饰器用于模板的字典中?

发布于 2025-01-01 21:13:48 字数 1409 浏览 1 评论 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 并选择到字典中,但我无权访问控制器的实例属性(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

愚人国度 2025-01-08 21:13:48

您始终可以使用 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 and tg.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

心房的律动 2025-01-08 21:13:48

这是我理解“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”的局部变量。我们更改并更新了它的一致性,然后将其作为新数据发送。

Here is my example for understanding "before_render" decorator:

#---=== 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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文