Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
flask-admin
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Python-Dev
flask-admin
Commits
ac8392b8
Commit
ac8392b8
authored
Dec 28, 2013
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed #416. More flexible menu system
parent
4466d365
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
148 additions
and
87 deletions
+148
-87
simple.py
examples/menu-external-links/simple.py
+4
-0
base.py
flask_admin/base.py
+21
-84
menu.py
flask_admin/menu.py
+115
-0
test_base.py
flask_admin/tests/test_base.py
+8
-3
No files found.
examples/menu-external-links/simple.py
View file @
ac8392b8
...
...
@@ -84,6 +84,10 @@ if __name__ == '__main__':
admin
.
add_link
(
NotAuthenticatedMenuLink
(
name
=
'Login'
,
endpoint
=
'login_view'
))
# Add links with categories
admin
.
add_link
(
MenuLink
(
name
=
'Google'
,
category
=
'Links'
,
url
=
'http://www.google.com/'
))
admin
.
add_link
(
MenuLink
(
name
=
'Mozilla'
,
category
=
'Links'
,
url
=
'http://mozilla.org/'
))
# Add logout link by endpoint
admin
.
add_link
(
AuthenticatedMenuLink
(
name
=
'Logout'
,
endpoint
=
'logout_view'
))
...
...
flask_admin/base.py
View file @
ac8392b8
from
functools
import
wraps
from
flask
import
Blueprint
,
render_template
,
url_for
,
abort
,
g
from
flask
import
Blueprint
,
render_template
,
abort
,
g
from
flask.ext.admin
import
babel
from
flask.ext.admin._compat
import
with_metaclass
from
flask.ext.admin
import
helpers
as
h
# For compatibility reasons import MenuLink
from
flask.ext.admin.menu
import
MenuCategory
,
MenuView
,
MenuLink
def
expose
(
url
=
'/'
,
methods
=
(
'GET'
,)):
"""
...
...
@@ -343,79 +346,6 @@ class AdminIndexView(BaseView):
return
self
.
render
(
self
.
_template
)
class
MenuItem
(
object
):
"""
Simple menu tree hierarchy.
"""
def
__init__
(
self
,
name
,
view
=
None
):
self
.
name
=
name
self
.
_view
=
view
self
.
_children
=
[]
self
.
_children_urls
=
set
()
self
.
_cached_url
=
None
self
.
url
=
None
if
view
is
not
None
:
self
.
url
=
view
.
url
def
add_child
(
self
,
view
):
self
.
_children
.
append
(
view
)
self
.
_children_urls
.
add
(
view
.
url
)
def
get_url
(
self
):
if
self
.
_view
is
None
:
return
None
if
self
.
_cached_url
:
return
self
.
_cached_url
self
.
_cached_url
=
url_for
(
'
%
s.
%
s'
%
(
self
.
_view
.
endpoint
,
self
.
_view
.
_default_view
))
return
self
.
_cached_url
def
is_active
(
self
,
view
):
if
view
==
self
.
_view
:
return
True
return
view
.
url
in
self
.
_children_urls
def
is_visible
(
self
):
if
self
.
_view
is
None
:
return
False
return
self
.
_view
.
is_visible
()
def
is_accessible
(
self
):
if
self
.
_view
is
None
:
return
False
return
self
.
_view
.
is_accessible
()
def
is_category
(
self
):
return
self
.
_view
is
None
def
get_children
(
self
):
return
[
c
for
c
in
self
.
_children
if
c
.
is_accessible
()
and
c
.
is_visible
()]
class
MenuLink
(
object
):
"""
Additional menu links.
"""
def
__init__
(
self
,
name
,
url
=
None
,
endpoint
=
None
):
self
.
name
=
name
self
.
url
=
url
self
.
endpoint
=
endpoint
def
get_url
(
self
):
return
self
.
url
or
url_for
(
self
.
endpoint
)
def
is_visible
(
self
):
return
True
def
is_accessible
(
self
):
return
True
class
Admin
(
object
):
"""
Collection of the admin views. Also manages menu structure.
...
...
@@ -492,7 +422,8 @@ class Admin(object):
# If app was provided in constructor, register view with Flask app
if
self
.
app
is
not
None
:
self
.
app
.
register_blueprint
(
view
.
create_blueprint
(
self
))
self
.
_add_view_to_menu
(
view
)
self
.
_add_view_to_menu
(
view
)
def
add_link
(
self
,
link
):
"""
...
...
@@ -501,26 +432,33 @@ class Admin(object):
:param link:
Link to add.
"""
self
.
_menu_links
.
append
(
link
)
if
link
.
category
:
self
.
_add_menu_item
(
link
,
link
.
category
)
else
:
self
.
_menu_links
.
append
(
link
)
def
_add_
view_to_menu
(
self
,
view
):
def
_add_
menu_item
(
self
,
menu_item
,
target_category
):
"""
Add a view to the menu tree
:param view:
View to add
"""
if
view
.
category
:
category
=
self
.
_menu_categories
.
get
(
view
.
category
)
if
target_
category
:
category
=
self
.
_menu_categories
.
get
(
target_
category
)
if
category
is
None
:
category
=
MenuItem
(
view
.
category
)
self
.
_menu_categories
[
view
.
category
]
=
category
category
=
MenuCategory
(
target_category
)
self
.
_menu_categories
[
target_category
]
=
category
self
.
_menu
.
append
(
category
)
category
.
add_child
(
MenuItem
(
view
.
name
,
view
)
)
category
.
add_child
(
menu_item
)
else
:
self
.
_menu
.
append
(
MenuItem
(
view
.
name
,
view
))
self
.
_menu
.
append
(
menu_item
)
def
_add_view_to_menu
(
self
,
view
):
self
.
_add_menu_item
(
MenuView
(
view
.
name
,
view
),
view
.
category
)
def
init_app
(
self
,
app
):
"""
...
...
@@ -536,7 +474,6 @@ class Admin(object):
# Register views
for
view
in
self
.
_views
:
app
.
register_blueprint
(
view
.
create_blueprint
(
self
))
self
.
_add_view_to_menu
(
view
)
def
_init_extension
(
self
):
if
not
hasattr
(
self
.
app
,
'extensions'
):
...
...
flask_admin/menu.py
0 → 100644
View file @
ac8392b8
from
flask
import
url_for
class
BaseMenu
(
object
):
"""
Base menu item
"""
def
__init__
(
self
,
name
):
self
.
name
=
name
self
.
_children
=
[]
def
add_child
(
self
,
menu
):
self
.
_children
.
append
(
menu
)
def
get_url
(
self
):
raise
NotImplemented
()
def
is_category
(
self
):
return
False
def
is_active
(
self
,
view
):
for
c
in
self
.
_children
:
if
c
.
is_active
(
view
):
return
True
return
False
def
is_visible
(
self
):
return
True
def
is_accessible
(
self
):
return
True
def
get_children
(
self
):
return
[
c
for
c
in
self
.
_children
if
c
.
is_accessible
()
and
c
.
is_visible
()]
class
MenuCategory
(
BaseMenu
):
"""
Menu category item.
"""
def
get_url
(
self
):
return
None
def
is_category
(
self
):
return
True
def
is_visible
(
self
):
for
c
in
self
.
_children
:
if
c
.
is_visible
():
return
True
return
False
def
is_accessible
(
self
):
for
c
in
self
.
_children
:
if
c
.
is_accessible
():
return
True
return
False
class
MenuView
(
BaseMenu
):
"""
Admin view menu item
"""
def
__init__
(
self
,
name
,
view
=
None
):
super
(
MenuView
,
self
)
.
__init__
(
name
)
self
.
_view
=
view
self
.
_cached_url
=
None
def
get_url
(
self
):
if
self
.
_view
is
None
:
return
None
if
self
.
_cached_url
:
return
self
.
_cached_url
self
.
_cached_url
=
url_for
(
'
%
s.
%
s'
%
(
self
.
_view
.
endpoint
,
self
.
_view
.
_default_view
))
return
self
.
_cached_url
def
is_active
(
self
,
view
):
if
view
==
self
.
_view
:
return
True
return
super
(
MenuView
,
self
)
.
is_active
(
view
)
def
is_visible
(
self
):
if
self
.
_view
is
None
:
return
False
return
self
.
_view
.
is_visible
()
def
is_accessible
(
self
):
if
self
.
_view
is
None
:
return
False
return
self
.
_view
.
is_accessible
()
class
MenuLink
(
BaseMenu
):
"""
Link item
"""
def
__init__
(
self
,
name
,
url
=
None
,
endpoint
=
None
,
category
=
None
):
super
(
MenuLink
,
self
)
.
__init__
(
name
)
self
.
category
=
category
self
.
url
=
url
self
.
endpoint
=
endpoint
def
get_url
(
self
):
return
self
.
url
or
url_for
(
self
.
endpoint
)
flask_admin/tests/test_base.py
View file @
ac8392b8
...
...
@@ -262,11 +262,16 @@ def test_submenu():
eq_
(
admin
.
_menu
[
1
]
.
name
,
'Test'
)
eq_
(
len
(
admin
.
_menu
[
1
]
.
_children
),
2
)
# Categories don't have URLs
and they're not accessible
# Categories don't have URLs
eq_
(
admin
.
_menu
[
1
]
.
get_url
(),
None
)
eq_
(
admin
.
_menu
[
1
]
.
is_accessible
(),
False
)
eq_
(
len
(
admin
.
_menu
[
1
]
.
get_children
()),
1
)
# Categories are only accessible if there is at least one accessible child
eq_
(
admin
.
_menu
[
1
]
.
is_accessible
(),
True
)
children
=
admin
.
_menu
[
1
]
.
get_children
()
eq_
(
len
(
children
),
1
)
ok_
(
children
[
0
]
.
is_accessible
())
def
test_delayed_init
():
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment