Add conditional sub-menu

718 views
Skip to first unread message

Omi Chiba

unread,
Apr 11, 2012, 12:24:29 PM4/11/12
to web...@googlegroups.com
The following menu works. It's add "Admin" menu next to "Price List" if the user has role "admin". Now, I want to add the "Admin" menu as sub-menu of "Price List" where it's right after the "Cut Charge Tables". How can I do this ?

response.menu = [('Home', False, URL('home','default','index'), []),
    (SPAN('Price List',_style='color:yellow'), True, URL('pricelist','default','index'), 
    [('Guideline',  False,  URL('pricelist','default','guideline')),
     ('Multiplier Tables',  False,  URL('pricelist','default','multitable')),
     ('Cut Charge Tables',  False,  URL('pricelist','default','cuttable')),
    ])]

if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))):
    response.menu += [('Admin',  False,  URL('admin')), ]

Bruno Rocha

unread,
Apr 11, 2012, 12:36:33 PM4/11/12
to web...@googlegroups.com
response.menu = [('Home', False, URL('home','default','index'), []),
    (SPAN('Price List',_style='color:yellow'), True, URL('pricelist','default','index'), 
    [('Guideline',  False,  URL('pricelist','default','guideline')),
     ('Multiplier Tables',  False,  URL('pricelist','default','multitable')),
     ('Cut Charge Tables',  False,  URL('pricelist','default','cuttable')),
    ('Admin',  False,  URL('admin')) if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))) else None
    ])]


or


if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))):
    response.menu[1][3] += [('Admin',  False,  URL('admin')), ]


On Wed, Apr 11, 2012 at 1:24 PM, Omi Chiba <ochi...@gmail.com> wrote:
response.menu = [('Home', False, URL('home','default','index'), []),
    (SPAN('Price List',_style='color:yellow'), True, URL('pricelist','default','index'), 
    [('Guideline',  False,  URL('pricelist','default','guideline')),
     ('Multiplier Tables',  False,  URL('pricelist','default','multitable')),
     ('Cut Charge Tables',  False,  URL('pricelist','default','cuttable')),
    ])]



--

Omi Chiba

unread,
Apr 11, 2012, 2:42:55 PM4/11/12
to web...@googlegroups.com
Thank Bruno, but both shows some errors.

1st one

Traceback (most recent call last):
  File "C:\web2py\gluon\restricted.py", line 205, in restricted
    exec ccode in environment
  File "C:\web2py\applications\home\views\default/index.html", line 64, in <module>
  File "C:\web2py\gluon\globals.py", line 182, in write
    self.body.write(xmlescape(data))
  File "C:\web2py\gluon\html.py", line 114, in xmlescape
    return data.xml()
  File "C:\web2py\gluon\html.py", line 2146, in xml
    return self.serialize(self.data, 0).xml()
  File "C:\web2py\gluon\html.py", line 2121, in serialize
    li.append(self.serialize(item[3], level+1))
  File "C:\web2py\gluon\html.py", line 2109, in serialize
    (name, active, link) = item[:3]
TypeError: 'NoneType' object is not subscriptable


2nd one

Traceback (most recent call last):
  File "C:\web2py\gluon\restricted.py", line 205, in restricted
    exec ccode in environment
  File "C:/web2py/applications/home/models/menu.py", line 33, in <module>
    response.menu[1][3] += [('Admin',  False,  URL('admin'))]
TypeError: 'tuple' object does not support item assignment

Cliff

unread,
Apr 12, 2012, 12:00:30 AM4/12/12
to web...@googlegroups.com
I have something like this working:

sub_menu = []
if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))):
    sub_menu = [('Admin',  False,  URL('admin')), ]
response.menu = [('Home', False, URL('home','default','index'), []),
    (SPAN('Price List',_style='color:yellow'), True, URL('pricelist','default','index'), 
    [('Guideline',  False,  URL('pricelist','default','guideline')),
     ('Multiplier Tables',  False,  URL('pricelist','default','multitable')),
     ('Cut Charge Tables',  False,  URL('pricelist','default','cuttable')),
     (sub_menu),
    ])]

Javier Pepe

unread,
Apr 12, 2012, 6:18:58 AM4/12/12
to web...@googlegroups.com
I was working on a set menu from the database. It's simple and it can be useful.
The model is simple, and has a condition to evaluate options when generating the menu items.
The evaluation was done using the function 'eval'.
Attach model.
To manage SQLFORM.grid use or what you like

db.define_table('menu',
                Field('posicion',type='integer'),
                Field('titulo',type='string'),
                Field('controlador',type='string'),
                Field('funcion',type='string'),
                Field('padre'),
                Field('condicion'),
               )   
db.menu.padre.requires = IS_IN_DB(db, db.menu.id,'%(titulo)s')
db.menu.padre.represent = lambda id,row: db.menu(id).titulo
db.menu.condicion.default = 'True'

response.title = settings.title
response.subtitle = settings.subtitle
response.meta.author = '%(author)s <%(author_email)s>' % settings
response.meta.keywords = settings.keywords
response.meta.description = settings.description
response.menu = [ ] 


def add_item(nivel):
    item = []
    for itemmenu in db((db.menu.padre == nivel) & (db.menu.id > 1)).select(orderby=db.menu.posicion):
        if eval(itemmenu.condicion):
            item.append([itemmenu.titulo,None,URL(itemmenu.controlador,itemmenu.funcion),add_item(itemmenu.id) ])
    return item

if auth.is_logged_in():
    response.menu = add_item(1)

Omi Chiba

unread,
Apr 12, 2012, 9:43:39 AM4/12/12
to web...@googlegroups.com
Cliff, 

Thank you for sharing code but now I got a different error. Maybe it cannot understand sub_menu contains three parameters..

Traceback (most recent call last):
  File "C:\web2py\gluon\restricted.py", line 205, in restricted
    exec ccode in environment
  File "C:\web2py\applications\home\views\default/index.html", line 64, in <module>
  File "C:\web2py\gluon\globals.py", line 182, in write
    self.body.write(xmlescape(data))
  File "C:\web2py\gluon\html.py", line 114, in xmlescape
    return data.xml()
  File "C:\web2py\gluon\html.py", line 2146, in xml
    return self.serialize(self.data, 0).xml()
  File "C:\web2py\gluon\html.py", line 2121, in serialize
    li.append(self.serialize(item[3], level+1))
  File "C:\web2py\gluon\html.py", line 2109, in serialize
    (name, active, link) = item[:3]
ValueError: need more than 0 values to unpack

Omi Chiba

unread,
Apr 12, 2012, 9:44:08 AM4/12/12
to web...@googlegroups.com
Nice approach. I will try for my another project !

Cliff

unread,
Apr 15, 2012, 10:52:01 PM4/15/12
to web...@googlegroups.com
Omi,

Sorry, my bad.  Been away.

Should be:
    sub_menu = [('Admin',  False,  URL('admin'), []), ] # Added empty list

Omi Chiba

unread,
Apr 15, 2012, 11:21:20 PM4/15/12
to web...@googlegroups.com
Cliff,

Thanks ! I'm on vacation but I will try when I come back but I'm sure it works !!

Omi Chiba

unread,
Apr 25, 2012, 9:17:46 AM4/25/12
to web...@googlegroups.com
Thanks again ! I came back from vacation and tried the code but I got different error...

 File "C:\web2py\gluon\dal.py", line 1386, in log_execute
ret = self.cursor.execute(*a, **b)
ProgrammingError: The cursor's connection has been closed.


sub_menu = [('Admin',  False,  URL('admin'), []), ] # Added empty list

response.menu = [('Home', False, URL('home','default','index'), []),
    (SPAN('Price List',_style='color:yellow'), True, URL('pricelist','default','index'), 
    [('Guideline',  False,  URL('pricelist','default','guideline')),
     ('Multiplier Tables',  False,  URL('pricelist','default','multitable')),
     ('Cut Charge Tables',  False,  URL('pricelist','default','cuttable')),
     (sub_menu),
    ])]

Cliff

unread,
Apr 27, 2012, 4:16:19 PM4/27/12
to web...@googlegroups.com
Sorry I didn't see this sooner.

I think all your menu items will want that empty list, and I see some do not.

Also I am confused about how a menu script could cause a dal to raise an exception.  Maybe somebody with a better knowledge of the internals will chime in here.

黄祥

unread,
Sep 4, 2013, 7:42:06 AM9/4/13
to web...@googlegroups.com
i found the same difficulty during add conditional sub menu, in my case the conditional is base on session. i've followed cliff hints above using sub_menu = [], it work well as long as the condition is meet (there is a session), but the problem occured when i clear the session. 
is there any solutions, hints for this?

thanks and best regards
stifan

黄祥

unread,
Sep 7, 2013, 12:51:24 AM9/7/13
to web...@googlegroups.com
('Admin',  False,  URL('admin')) if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))) else None
it's not worked it raise an error :
TypeError: 'NoneType' object is not subscriptable

should be
('Admin',  False,  URL('admin')) if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))) else ('',  False,  False)

or
sub_menu = []
if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))):
    sub_menu = [('Admin',  False,  URL('admin')), ]

should be
sub_menu = [('',  False,  False), ]
if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))):
    sub_menu = [('Admin',  False,  URL('admin')), ]

but it will leave an empty little space under the last menu 'Cut Charge Tables'

any idea how to make it clean?

thanks and best regards,
stifan

jim kaubisch

unread,
Feb 8, 2018, 5:10:33 PM2/8/18
to web2py-users
this is an old thread, but I needed to do add a conditional piece to a menu - but had trouble with all the options below.

Then I realized that response.menu is a list, hence rather than 

if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))):
    response.menu += [('Admin',  False,  URL('admin')), ]

the following:

if (auth.user_id != None) and ((auth.has_membership(role = 'admin'))):
    response.menu.append( [('Admin',  False,  URL('admin')), ])

worked for me :-) 

Mine actually included simple dropdown submenus...

if (auth.user_id != None) and (auth.has_membership(role = 'admin')):
    response.menu.append ([' Admin',  False,  None,
                        [
                            ['Show Meta Data' , False, URL('my_admin', 'show_meta_data' , vars=dict(meta_op='meta_show'))],
                            ['Backup Database', False, URL('my_admin', 'backup_database', vars=dict(db_op  ='db_backup'))],
                            ['Backup Database', False, URL('my_admin', 'backup_database', vars=dict(db_op  ='db_restore'))]
                        ]
                     ])
Reply all
Reply to author
Forward
0 new messages