Multi-level (tree-ish) navigation

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# 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)

More like this

  1. Menu/navigation bars in a tag by ep 5 years, 9 months ago
  2. Using URLs for highlighting sections in menu by diverman 2 years, 9 months ago
  3. Active link by ronnie 1 year, 5 months ago
  4. Google Contacts API friend finder by dgouldin 5 years, 1 month ago
  5. URL Query Parameter Menu by drg006 5 years, 12 months ago

Comments

jpic (on March 15, 2009):

Update:

  • Refactored Menu by inheriting from builtin list.
  • Added a factory.

#

(Forgotten your password?)