Including tg.url, request, etc in a TG2.2.0/TW(0.9.12) widget template

63 views
Skip to first unread message

Shane

unread,
May 3, 2013, 1:16:55 AM5/3/13
to turbo...@googlegroups.com
Hello,

I am building a JBar menubar widget for a TG application.  I was planning to build different menubars by subclassing a base JBar(Widget) class and modifying the template.  The problem is that I need to use tg.url and request objects to modify the menu from the controller.  When I call the display() method on my HomeMenuBar, I get:

UndefinedError: "request" not defined

So, I'm not getting access to request (or tg.url) in the environment of my widget template.  How do I do this?

To summarize what is happening (ToscaWidgets 0.9.12, TurboGears2 2.2.0):

class HomeMenuBar (JBar):
    template=('''
        <html xmlns="http://www.w3.org/1999/xhtml"
              xmlns:py="http://genshi.edgewall.org/"
              xmlns:xi="http://www.w3.org/2001/XInclude"
              py:attrs="attrs"
              py:strip="">
     
        <ul class="${menu_css}">
            <li><a py:if="request.identity" href="${tg.url('/about')}">About</a></li>           
            <li><a py:if="request.identity" href='/pdf/User Manual.pdf'>Help</a></li>
            <li><a py:if="request.identity" id="login" class="loginlogout" href="${tg.url('/logout_handler')}">Logout</a></li>
        </ul>
       
        </html>
    ''')
home_menu_bar=HomeMenuBar('home_menu')

I create the object once in my widgets.MenuBar.py and pass from the controller to another template in the tmpl_context:

@expose('MyApp.templates.TableView')
@expose('json')
def home (self, *args, **kw):
   ...
   tmpl_context.menu_bar=MenuBars.home_menu_bar
   return {}

In my TableView.html template, I include:

<xi:include href="master.html" />

which finally brings in the menu bar across the top of each page:
           ....
<div py:if="hasattr(tmpl_context, 'menu_bar')" id="menu_bar_container">
    ${tmpl_context.menu_bar.display()}
</div>
           ....

I had previously passed a genshi method name from controller to template in order to accomplish the same task, but I wanted to put the menubar into a widget, as this allows more flexibility to modify the menu in the controller.

Thank you,

Shane

Moritz Schlarb

unread,
May 3, 2013, 2:46:45 AM5/3/13
to turbo...@googlegroups.com
Use the lazy variant that gets evaluated as late as possible:
tg.lurl()

Shane

unread,
May 3, 2013, 3:27:44 PM5/3/13
to turbo...@googlegroups.com
Moritz,

Didn't know about the lurl(), but I don't think that is the root of the problem.  I don't have access to any of the tg namespace.  The problem seems to be in widget.display().  I can pull up a shell, make a jbar=HomeMenuBar('home_dom_id')) object but calling jbar.display() (or jbar.render()) throws the same "request" or "tg" not defined error.

It seems like the template code for widgets is being evaluated separately from that of the master.html template (which makes sense), I just don't know how to import tg or request (or other TG modules) into a widget's namespace.

Looking through the various widget templates, I haven't seen examples of tg or other namespaces being used.  Perhaps I am going about this the wrong way?

- Shane

Alessandro Molina

unread,
May 3, 2013, 6:27:34 PM5/3/13
to TurboGears .
Hi,

as you already noticed widgets are rendered in a different context from the page templates, widgets templates are usually not meant for doing much computation. You should prepare everything you need inside the template inside the "prepare" method of the widget.

In your case you HomeBarMenu would be something like:

class HomeMenuBar (JBar):
   template = ' ... '

   def prepare(self):
       super(HomeMenuBar, self).prepare()
       self.user_logged = tg.request.identity is not None
       self.urls = {'about': tg.url('/about'), 'logout':tg.url('/logout_handler')}

and so on... Then it will be possible to access the variables inside the template as w.user_logged and w.urls


--
You received this message because you are subscribed to the Google Groups "TurboGears" group.
To unsubscribe from this group and stop receiving emails from it, send an email to turbogears+...@googlegroups.com.
To post to this group, send email to turbo...@googlegroups.com.
Visit this group at http://groups.google.com/group/turbogears?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Craig Small

unread,
May 4, 2013, 8:36:16 AM5/4/13
to TurboGears .
On Sat, May 04, 2013 at 12:27:34AM +0200, Alessandro Molina wrote:
> as you already noticed widgets are rendered in a different context from
> the page templates, widgets templates are usually not meant for doing much
> computation. You should prepare everything you need inside the template
> inside the "prepare" method of the widget.
If you really need tg.url in your widget, do a hack like this in prepare
self.url = tg.url
the template can then use w.url

Alessandro is probably right though.

- Craig

--
Craig Small VK2XLZ http://enc.com.au/ csmall at : enc.com.au
Debian GNU/Linux http://www.debian.org/ csmall at : debian.org
GPG fingerprint: 5D2F B320 B825 D939 04D2 0519 3938 F96B DF50 FEA5

Shane

unread,
May 7, 2013, 2:45:11 AM5/7/13
to turbo...@googlegroups.com, csm...@enc.com.au
Craig and Alessandro,

Thank you for your help.  I ended up doing as Alessandro suggested and passing urls/labels in the update_params method (Still in old TW).  All permission logic is handled in this method and only menu items that are visible to a particular user are passed.

I did try passing the entire tg module as Craig mentioned.  It worked, but I have no idea what performance or other penalty may be incurred.  I guess it boils down to where you want to do the majority of your menubar logic, and I am happy to keep it out of the template.

- Shane
Reply all
Reply to author
Forward
0 new messages