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
80b8377d
Commit
80b8377d
authored
Mar 20, 2012
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactoring, column renaming.
parent
4f019346
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
148 additions
and
48 deletions
+148
-48
TODO.txt
TODO.txt
+3
-6
simple.py
examples/sqla/simple.py
+2
-1
sqlamodel.py
flask_adminex/ext/sqlamodel.py
+12
-15
model.py
flask_adminex/model.py
+127
-26
list.html
flask_adminex/templates/admin/model/list.html
+4
-0
No files found.
TODO.txt
View file @
80b8377d
- Core
- Pregenerate URLs for menu
- Override base URL (/admin/)
- Model
a
dmin
- Ability to override sortable fields
- Model
A
dmin
Ability to sort by fields that are not visible?
- SQLA Model Admin
- Sort by foreign key
- Validation of the joins in the query
- Automatic joined load for foreign keys
- Automatic PK detection
- Ability to override displayed form fields
- Ability to rename list columns
- Ability to change form without messing with form creation
- Filtering
- Many2Many editing
-
Many2One
editor
-
One2Many
editor
- File admin
- Documentation
- Examples
...
...
examples/sqla/simple.py
View file @
80b8377d
...
...
@@ -49,7 +49,8 @@ def index():
class
PostAdmin
(
sqlamodel
.
ModelView
):
list_columns
=
(
'title'
,
'user'
)
sortable_columns
=
dict
(
title
=
'title'
,
user
=
User
.
username
)
sortable_columns
=
(
'title'
,
(
'user'
,
User
.
username
))
rename_columns
=
dict
(
title
=
'Tiiitle'
)
def
__init__
(
self
,
session
):
super
(
PostAdmin
,
self
)
.
__init__
(
Post
,
session
)
...
...
flask_adminex/ext/sqlamodel.py
View file @
80b8377d
...
...
@@ -71,7 +71,7 @@ class ModelView(BaseModelView):
if
column
.
foreign_keys
or
column
.
primary_key
:
continue
columns
.
append
(
(
p
.
key
,
self
.
prettify_name
(
p
.
key
))
)
columns
.
append
(
p
.
key
)
return
columns
...
...
@@ -81,11 +81,7 @@ class ModelView(BaseModelView):
mapper
=
self
.
model
.
_sa_class_manager
.
mapper
for
p
in
mapper
.
iterate_properties
:
if
isinstance
(
p
,
RelationshipProperty
):
if
p
.
direction
is
MANYTOONE
:
# TODO: Detect PK
columns
[
p
.
key
]
=
'
%
s.id'
%
p
.
target
.
name
elif
isinstance
(
p
,
ColumnProperty
):
if
isinstance
(
p
,
ColumnProperty
):
# TODO: Check for multiple columns
column
=
p
.
columns
[
0
]
...
...
@@ -103,22 +99,20 @@ class ModelView(BaseModelView):
converter
=
AdminModelConverter
(
self
.
session
))
# Database-related API
def
get_list
(
self
,
page
,
sort_column
,
sort_desc
):
def
get_list
(
self
,
page
,
sort_column
,
sort_desc
,
execute
=
True
):
query
=
self
.
session
.
query
(
self
.
model
)
count
=
query
.
count
()
# Sorting
column
=
self
.
_get_column_by_idx
(
sort_column
)
if
column
is
not
None
:
name
=
column
[
0
]
if
name
in
self
.
_sortable_columns
:
sort_field
=
self
.
_sortable_columns
[
name
]
if
sort_column
is
not
None
:
if
sort_column
in
self
.
_sortable_columns
:
sort_field
=
self
.
_sortable_columns
[
sort_column
]
# Try to handle it as a string
if
isinstance
(
sort_field
,
basestring
):
# Create automatic join if string contains dot
# Create automatic join against a table if column name
# contains dot.
if
'.'
in
sort_field
:
parts
=
sort_field
.
split
(
'.'
,
1
)
query
=
query
.
join
(
parts
[
0
])
...
...
@@ -139,7 +133,10 @@ class ModelView(BaseModelView):
query
=
query
.
limit
(
self
.
page_size
)
return
count
,
query
.
all
()
if
execute
:
query
=
query
.
all
()
return
count
,
query
def
get_one
(
self
,
id
):
return
self
.
session
.
query
(
self
.
model
)
.
get
(
id
)
...
...
flask_adminex/model.py
View file @
80b8377d
...
...
@@ -50,26 +50,39 @@ class BaseModelView(BaseView):
class MyModelView(BaseModelView):
list_columns = ('name', 'last_name', 'email')
"""
rename_columns
=
None
"""
Dictionary where key is column name and value is string to display.
If you want to rename column, use tuple instead of the name,
where first value is field name and second is display name.
You can also mix these values::
For example::
class MyModelView(BaseModelView):
list_columns = (('name', 'First Name'),
('last_name', 'Family Name'),
'email')
rename_columns = dict(name='Name', last_name='Last Name')
"""
sortable_columns
=
None
"""
Dictionary of the sortable columns names and property references
.
Collection of the sortable columns for the list view
.
If set to `None`, will get them from the model.
For example::
class MyModelView(BaseModelView):
sortable_columns = dict(name='name', user='user.id')
sortable_columns = ('name', 'last_name')
If you want to explicitly specify field/column to be used while
sorting, you can use tuple::
class MyModelView(BaseModelView):
sortable_columns = ('name', ('user', 'user.username'))
For SQLAlchemy models, you can pass attribute instead of the string
too::
class MyModelView(BaseModelView):
sortable_columns = ('name', ('user', User.username))
"""
form_columns
=
None
...
...
@@ -136,9 +149,7 @@ class BaseModelView(BaseView):
Expected return format is list of tuples with field name and
display text. For example::
[('name', 'Name'),
('email', 'Email'),
('last_name', 'Last Name')]
['name', 'first_name', 'last_name']
"""
raise
NotImplemented
(
'Please implement scaffold_list_columns method'
)
...
...
@@ -148,18 +159,20 @@ class BaseModelView(BaseView):
set, returns it. Otherwise calls `scaffold_list_columns`
to generate list from the model.
"""
result
=
[]
if
self
.
list_columns
is
None
:
columns
=
self
.
scaffold_list_columns
()
else
:
columns
=
[]
columns
=
self
.
list_columns
for
c
in
self
.
list_
columns
:
if
not
isinstance
(
c
,
tuple
)
:
columns
.
append
((
c
,
self
.
prettify_name
(
c
)
))
for
c
in
columns
:
if
self
.
rename_columns
and
c
in
self
.
rename_columns
:
result
.
append
((
c
,
self
.
rename_columns
[
c
]
))
else
:
columns
.
append
(
c
)
result
.
append
((
c
,
self
.
prettify_name
(
c
))
)
return
columns
return
result
def
scaffold_sortable_columns
(
self
):
"""
...
...
@@ -180,10 +193,17 @@ class BaseModelView(BaseView):
`scaffold_sortable_columns` to get them from the model.
"""
if
self
.
sortable_columns
is
None
:
print
self
.
__class__
.
__name__
return
self
.
scaffold_sortable_columns
()
else
:
return
self
.
sortable_columns
result
=
dict
()
for
c
in
self
.
sortable_columns
:
if
isinstance
(
c
,
tuple
):
result
[
c
[
0
]]
=
c
[
1
]
else
:
result
[
c
]
=
c
return
result
def
scaffold_form
(
self
):
"""
...
...
@@ -226,9 +246,18 @@ class BaseModelView(BaseView):
# Helpers
def
is_sortable
(
self
,
name
):
"""
Verify if column is sortable.
`name`
Column name.
"""
return
name
in
self
.
_sortable_columns
def
_get_column_by_idx
(
self
,
idx
):
"""
Return column index by
"""
if
idx
is
None
or
idx
<
0
or
idx
>=
len
(
self
.
_list_columns
):
return
None
...
...
@@ -245,31 +274,82 @@ class BaseModelView(BaseView):
`page`
Page number, 0 based. Can be set to None if it is first page.
`sort_field`
Sort
field index in the `self.list_columns`
or None.
Sort
column name
or None.
`sort_desc`
If set to True, sorting is in descending order.
"""
raise
NotImplemented
(
'Please implement get_list method'
)
def
get_one
(
self
,
id
):
"""
Return one model by its id.
Must be implemented in the child class.
`id`
Model id
"""
raise
NotImplemented
(
'Please implement get_one method'
)
# Model handlers
def
create_model
(
self
,
form
):
"""
Create model from the form.
Returns `True` if operation succeeded.
Must be implemented in the child class.
`form`
Form instance
"""
raise
NotImplemented
()
def
update_model
(
self
,
form
,
model
):
"""
Update model from the form.
Returns `True` if operation succeeded.
Must be implemented in the child class.
`form`
Form instance
`model`
Model instance
"""
raise
NotImplemented
()
def
delete_model
(
self
,
model
):
"""
Delete model.
Returns `True` if operation succeeded.
Must be implemented in the child class.
`model`
Model instance
"""
raise
NotImplemented
()
# Various helpers
def
prettify_name
(
self
,
name
):
"""
Prettify pythonic variable name.
For example, 'hello_world' will be converted to 'Hello World'
`name`
Name to prettify
"""
return
' '
.
join
(
x
.
capitalize
()
for
x
in
name
.
split
(
'_'
))
# URL generation helper
def
_get_extra_args
(
self
):
"""
Return arguments from query string.
"""
page
=
request
.
args
.
get
(
'page'
,
0
,
type
=
int
)
sort
=
request
.
args
.
get
(
'sort'
,
None
,
type
=
int
)
sort_desc
=
request
.
args
.
get
(
'desc'
,
None
,
type
=
int
)
...
...
@@ -277,16 +357,37 @@ class BaseModelView(BaseView):
return
page
,
sort
,
sort_desc
def
_get_url
(
self
,
view
,
page
,
sort
,
sort_desc
):
"""
Generate page URL with current page, sort column and
other parameters.
`view`
View name
`page`
Page number
`sort`
Sort column index
`sort_desc`
Use descending sorting order
"""
return
url_for
(
view
,
page
=
page
,
sort
=
sort
,
desc
=
sort_desc
)
# Views
@
expose
(
'/'
)
def
index_view
(
self
):
"""
List view
"""
# Grab parameters from URL
page
,
sort
,
sort_desc
=
self
.
_get_extra_args
()
page
,
sort_idx
,
sort_desc
=
self
.
_get_extra_args
()
# Map column index to column name
sort_column
=
self
.
_get_column_by_idx
(
sort_idx
)
if
sort_column
is
not
None
:
sort_column
=
sort_column
[
0
]
# Get count and data
count
,
data
=
self
.
get_list
(
page
,
sort
,
sort_desc
)
count
,
data
=
self
.
get_list
(
page
,
sort
_column
,
sort_desc
)
# Calculate number of pages
num_pages
=
count
/
self
.
page_size
...
...
@@ -299,7 +400,7 @@ class BaseModelView(BaseView):
if
p
==
0
:
p
=
None
return
self
.
_get_url
(
'.index_view'
,
p
,
sort
,
sort_desc
)
return
self
.
_get_url
(
'.index_view'
,
p
,
sort
_idx
,
sort_desc
)
def
sort_url
(
column
,
invert
=
False
):
desc
=
None
...
...
@@ -320,13 +421,13 @@ class BaseModelView(BaseView):
sortable_columns
=
self
.
_sortable_columns
,
# Stuff
get_value
=
get_value
,
return_url
=
self
.
_get_url
(
'.index_view'
,
page
,
sort
,
sort_desc
),
return_url
=
self
.
_get_url
(
'.index_view'
,
page
,
sort
_idx
,
sort_desc
),
# Pagination
pager_url
=
pager_url
,
num_pages
=
num_pages
,
page
=
page
,
# Sorting
sort_column
=
sort
,
sort_column
=
sort
_idx
,
sort_desc
=
sort_desc
,
sort_url
=
sort_url
)
...
...
flask_adminex/templates/admin/model/list.html
View file @
80b8377d
...
...
@@ -9,6 +9,7 @@
{% set column = 0 %}
{% for c, name in list_columns %}
<th>
{% if view.is_sortable(c) %}
{% if sort_column == column %}
<a
href=
"{{ sort_url(column, True) }}"
>
{{ name }}
...
...
@@ -21,6 +22,9 @@
{% else %}
<a
href=
"{{ sort_url(column) }}"
>
{{ name }}
</a>
{% endif %}
{% else %}
{{ name }}
{% endif %}
</th>
{% set column = column + 1 %}
{% endfor %}
...
...
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