# Works flawlessly with http://www.dynamicdrive.com/style/csslibrary/item/jquery_multi_level_css_menu_horizontal_blue/ class Menu ( list ): def render ( self , ul = True ): html = '' if ul : html += '<ul>' for menuitem in self : html += menuitem . render () if ul : html += '</ul>' return html def add ( self , title , url = None ): item = MenuItem ( title , url ) self . append ( item ) return item class MenuItem ( Menu ): def __init__ ( self , title , url = None ): super ( MenuItem , self ) . __init__ () self . title = title if not url : self . url = '' else : self . url = url def render_inside ( self ): html = '<a href="' + self . url + '" title="' + self . title + '">' + self . title + '</a>' return html def render ( self ): inside = self . render_inside () if len ( self ) == 0 : html = '<li>' + inside + '</li>' else : html = '<li>' + inside + '<ul>' for menuitem in self : html += menuitem . render () html += '</ul></li>' return html def append_to_menus ( self , menus ): for menu in menus : menu . append ( self ) return self class MenuFactories ( object ): def __init__ ( self , source , menu = None ): self . source = source if not menu : menu = Menu () self . menu = menu if isinstance ( source , dict ): self . parse_dict ( self . source , self . menu ) def parse_dict ( self , source , menu ): for k , v in source . items (): if isinstance ( v , dict ): self . parse_dict ( v , menu . add ( k ) ) else : menu . add ( k , v ) return menu # Example context processor: def nav ( request ): nav = {} immo = "Immobilier" user = "Utilisateur" admin = "Administration" menu = Menu () immo = menu . add ( immo ) user = menu . add ( user ) acheter = immo . add ( "Acheter" ) investissement = acheter . add ( "Investissement locatif" ) accession = acheter . add ( "Accession" ) louer = immo . add ( "Louer" ) menus = investissement , accession , louer MenuItem ( "Chambres" , "/cherche/chambres/accession/profil" ) . append_to_menus ( menus ) MenuItem ( "Appartements" , "/cherche/appartements/accession/profil" ) . append_to_menus ( menus ) MenuItem ( "Villas, Maisons, Pavillons ..." , "/cherche/villas-maisons-pavillons/accession/profil" ) . append_to_menus ( menus ) MenuItem ( "Masionn de ville, village ..." , "/cherche/maisons-de-ville-village/accession/profil" ) . append_to_menus ( menus ) MenuItem ( "Maisons de caractère" , "/cherche/maisons-de-caractère/accession/profil" ) . append_to_menus ( menus ) MenuItem ( "Parking, garages ..." , "/cherche/parkings-garages/accession/profil" ) . append_to_menus ( menus ) MenuItem ( "Programmes neufs" ) . append_to_menus ( menus ) if request . user . is_staff : admin = menu . add ( "Administration" ) admin . add ( "Rechercher des utilisateurs" , "/profiles/" ) admin . add ( "Interface Complête" , "/admin" ) if request . user . is_authenticated (): # if "Partenaires" in request.user.groups.all() user . add ( "Mes dernières recherches" , "/mesrecherches/" ) user . add ( "Mes coordonnées" , "/profiles/edit" ) user . add ( "Déconnection" , "/accounts/logout" ) else : user . add ( "Recevoir un nouveau mot de passe" , "/accounts/password/reset/" ) user . add ( "Enregistrement d'un nouveau compte" , "/accounts/register/" ) user . add ( "Authentification" , "/accounts/login" ) # in the template, use {{ nav|safe }} return { 'nav' : menu . render () } # Example using the factory: def nav ( request ): menu = menus . Menu () if request . user . is_staff : nav = { "Portefeuille" : { "Saisie d'une nouvelle location" : '/admin/immo/location/add/' , "Saisie d'un nouveau LCP (Immo d'entreprise)" : '/admin/immo/lcp/add' , "Saisie d'un nouveau terrain" : '/admin/immo/terrain/add/' , "Saisie d'un nouveau lot" : '/admin/immo/lot/add/' , "Statistique visite lot" : '/statistiques/' , "Rapprochement lot/contact" : '/admin/immo/rapprochement/add/' , "Rapprochement contact/lot" : '/admin/immo/rapprochement/add/' , }, "Contact" : { "Saisie d'un nouveau contact" : '/admin/auth/user/add/' , "Liste des contacts" : '/admin/auth/user/' , "Liste des demandes" : '/admin/immo/demande/' , }, "Evenement" : { "Saisie d'un evenement" : '/admin/crm/evenement/add/' , "Liste des evenements" : '/admin/crm/evenement/' }, "Reservation" : { "Saisie de reservation de location" : '/admin/resa/location/add/' , "Liste des reservations de location" : '/admin/resa/location/' , "Saise de compromis de vente" : '/admin/resa/vente/add/' , "Liste des compromis de ventes" : '/admin/resa/vente/' , }, "Administration" : { "Analyse du portefeuille" : { "LCP (Immo d'entreprise)" : '/admin/immo/lcp/' , "Terrain" : '/admin/immo/terrain/' , "Lot" : '/admin/immo/lot/' , }, "Analyse des activités des négociateur" : '/?/' , "Synthèse des rémunérations" : '/?/' , "Gestion des utilisateurs" : '/admin/auth/user/' , "Documents agence" : '/admin/immo/document/' , "Paramétrage du logiciel" : '/admin/' , "Paramétrage site Agence" : '/admin/flatpages/flatpage/' , }, } f = menus . MenuFactories ( nav , menu )