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
fedd6792
Commit
fedd6792
authored
Mar 29, 2012
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PK name is now scaffolded from the model. More docs.
parent
73ed6524
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
110 additions
and
8 deletions
+110
-8
TODO.txt
TODO.txt
+1
-0
view.py
flask_adminex/ext/sqlamodel/view.py
+9
-0
base.py
flask_adminex/model/base.py
+34
-6
filters.py
flask_adminex/model/filters.py
+64
-0
list.html
flask_adminex/templates/admin/model/list.html
+2
-2
No files found.
TODO.txt
View file @
fedd6792
...
@@ -12,6 +12,7 @@
...
@@ -12,6 +12,7 @@
- Paginator class
- Paginator class
- Custom CSS/JS in admin interface
- Custom CSS/JS in admin interface
- SQLA Model Admin
- SQLA Model Admin
- Do not rely on id as a primary key
- Built-in filtering support
- Built-in filtering support
- Many2Many support
- Many2Many support
- Verify if it is working properly
- Verify if it is working properly
...
...
flask_adminex/ext/sqlamodel/view.py
View file @
fedd6792
...
@@ -267,6 +267,15 @@ class ModelView(BaseModelView):
...
@@ -267,6 +267,15 @@ class ModelView(BaseModelView):
return
self
.
model
.
_sa_class_manager
.
mapper
.
iterate_properties
return
self
.
model
.
_sa_class_manager
.
mapper
.
iterate_properties
# Scaffolding
# Scaffolding
def
scaffold_pk
(
self
):
for
p
in
self
.
_get_model_iterator
():
if
hasattr
(
p
,
'columns'
):
for
c
in
p
.
columns
:
if
c
.
primary_key
:
return
p
.
key
return
None
def
scaffold_list_columns
(
self
):
def
scaffold_list_columns
(
self
):
"""
"""
Return list of columns from the model.
Return list of columns from the model.
...
...
flask_adminex/model/base.py
View file @
fedd6792
...
@@ -114,7 +114,12 @@ class BaseModelView(BaseView):
...
@@ -114,7 +114,12 @@ class BaseModelView(BaseView):
"""
"""
Collection of the column filters.
Collection of the column filters.
TBD: Doc
Can contain either field names or instances of :class:`flask.ext.admin.model.filters.BaseFilter` classes.
For example:
class MyModelView(BaseModelView):
column_filters = ('user', 'email')
"""
"""
form_columns
=
None
form_columns
=
None
...
@@ -196,6 +201,12 @@ class BaseModelView(BaseView):
...
@@ -196,6 +201,12 @@ class BaseModelView(BaseView):
"""
"""
Refresh various cached variables.
Refresh various cached variables.
"""
"""
# Primary key
self
.
_primary_key
=
self
.
scaffold_pk
()
if
self
.
_primary_key
is
None
:
raise
Exception
(
'Model
%
s does not have primary key.'
%
self
.
model
.
__name__
)
# List view
# List view
self
.
_list_columns
=
self
.
get_list_columns
()
self
.
_list_columns
=
self
.
get_list_columns
()
self
.
_sortable_columns
=
self
.
get_sortable_columns
()
self
.
_sortable_columns
=
self
.
get_sortable_columns
()
...
@@ -219,7 +230,17 @@ class BaseModelView(BaseView):
...
@@ -219,7 +230,17 @@ class BaseModelView(BaseView):
self
.
_filter_names
=
None
self
.
_filter_names
=
None
self
.
_filter_types
=
None
self
.
_filter_types
=
None
# Public API
# Primary key
def
scaffold_pk
(
self
):
"""
Find model primary key name
"""
raise
NotImplemented
()
def
get_pk_value
(
self
,
model
):
return
getattr
(
model
,
self
.
_primary_key
)
# List view
def
scaffold_list_columns
(
self
):
def
scaffold_list_columns
(
self
):
"""
"""
Return list of the model field names. Must be implemented in
Return list of the model field names. Must be implemented in
...
@@ -308,6 +329,9 @@ class BaseModelView(BaseView):
...
@@ -308,6 +329,9 @@ class BaseModelView(BaseView):
"""
"""
Verify that provided filter object is valid.
Verify that provided filter object is valid.
Override in model backend implementation to verify if
provided filter type is allowed.
`filter`
`filter`
Filter object to verify.
Filter object to verify.
"""
"""
...
@@ -316,6 +340,9 @@ class BaseModelView(BaseView):
...
@@ -316,6 +340,9 @@ class BaseModelView(BaseView):
def
get_filters
(
self
):
def
get_filters
(
self
):
"""
"""
Return list of filter objects.
Return list of filter objects.
If your model backend implementation does not support filters,
override this method and return `None`.
"""
"""
if
self
.
column_filters
:
if
self
.
column_filters
:
collection
=
[]
collection
=
[]
...
@@ -330,8 +357,6 @@ class BaseModelView(BaseView):
...
@@ -330,8 +357,6 @@ class BaseModelView(BaseView):
else
:
else
:
collection
.
append
(
n
)
collection
.
append
(
n
)
print
collection
return
collection
return
collection
else
:
else
:
return
None
return
None
...
@@ -504,8 +529,10 @@ class BaseModelView(BaseView):
...
@@ -504,8 +529,10 @@ class BaseModelView(BaseView):
value
=
request
.
args
.
get
(
param
+
'v'
,
None
)
value
=
request
.
args
.
get
(
param
+
'v'
,
None
)
if
idx
>=
0
and
idx
<
len
(
self
.
_filters
):
if
idx
>=
0
and
idx
<
len
(
self
.
_filters
):
if
self
.
_filters
[
idx
]
.
validate
(
value
):
flt
=
self
.
_filters
[
idx
]
filters
.
append
((
idx
,
value
))
if
flt
.
validate
(
value
):
filters
.
append
((
idx
,
flt
.
clean
(
value
)))
else
:
else
:
filters
=
None
filters
=
None
...
@@ -610,6 +637,7 @@ class BaseModelView(BaseView):
...
@@ -610,6 +637,7 @@ class BaseModelView(BaseView):
sortable_columns
=
self
.
_sortable_columns
,
sortable_columns
=
self
.
_sortable_columns
,
# Stuff
# Stuff
enumerate
=
enumerate
,
enumerate
=
enumerate
,
gey_pk_value
=
self
.
get_pk_value
,
get_value
=
get_value
,
get_value
=
get_value
,
return_url
=
self
.
_get_url
(
'.index_view'
,
return_url
=
self
.
_get_url
(
'.index_view'
,
page
,
page
,
...
...
flask_adminex/model/filters.py
View file @
fedd6792
class
BaseFilter
(
object
):
class
BaseFilter
(
object
):
"""
Base filter class.
"""
def
__init__
(
self
,
name
,
options
=
None
,
data_type
=
None
):
def
__init__
(
self
,
name
,
options
=
None
,
data_type
=
None
):
"""
Constructor.
`name`
Displayed name
`options`
List of fixed options. If provided, will use drop down instead of textbox.
`data_type`
Client-side widget type to use.
"""
self
.
name
=
name
self
.
name
=
name
self
.
options
=
options
self
.
options
=
options
self
.
data_type
=
data_type
self
.
data_type
=
data_type
def
get_options
(
self
,
view
):
def
get_options
(
self
,
view
):
"""
Return list of predefined options.
Override to customize behavior.
`view`
Associated administrative view class.
"""
return
self
.
options
return
self
.
options
def
validate
(
self
,
value
):
def
validate
(
self
,
value
):
"""
Validate value.
If value is valid, returns `True` and `False` otherwise.
`value`
Value to validate
"""
return
True
return
True
def
clean
(
self
,
value
):
"""
Parse value into python format.
`value`
Value to parse
"""
return
value
def
apply
(
self
,
query
):
def
apply
(
self
,
query
):
"""
Apply search criteria to the query and return new query.
`query`
Query
"""
raise
NotImplemented
()
raise
NotImplemented
()
def
__unicode__
(
self
):
def
__unicode__
(
self
):
...
@@ -19,6 +63,9 @@ class BaseFilter(object):
...
@@ -19,6 +63,9 @@ class BaseFilter(object):
# Customized filters
# Customized filters
class
BaseBooleanFilter
(
BaseFilter
):
class
BaseBooleanFilter
(
BaseFilter
):
"""
Base boolean filter, uses fixed list of options.
"""
def
__init__
(
self
,
name
,
data_type
=
None
):
def
__init__
(
self
,
name
,
data_type
=
None
):
super
(
BaseBooleanFilter
,
self
)
.
__init__
(
name
,
super
(
BaseBooleanFilter
,
self
)
.
__init__
(
name
,
((
'1'
,
'Yes'
),
(
'0'
,
'No'
)),
((
'1'
,
'Yes'
),
(
'0'
,
'No'
)),
...
@@ -29,6 +76,9 @@ class BaseBooleanFilter(BaseFilter):
...
@@ -29,6 +76,9 @@ class BaseBooleanFilter(BaseFilter):
class
BaseDateFilter
(
BaseFilter
):
class
BaseDateFilter
(
BaseFilter
):
"""
Base Date filter. Uses client-side date picker control.
"""
def
__init__
(
self
,
name
,
options
=
None
):
def
__init__
(
self
,
name
,
options
=
None
):
super
(
BaseDateFilter
,
self
)
.
__init__
(
name
,
super
(
BaseDateFilter
,
self
)
.
__init__
(
name
,
options
,
options
,
...
@@ -40,6 +90,9 @@ class BaseDateFilter(BaseFilter):
...
@@ -40,6 +90,9 @@ class BaseDateFilter(BaseFilter):
class
BaseDateTimeFilter
(
BaseFilter
):
class
BaseDateTimeFilter
(
BaseFilter
):
"""
Base DateTime filter. Uses client-side date picker control.
"""
def
__init__
(
self
,
name
,
options
=
None
):
def
__init__
(
self
,
name
,
options
=
None
):
super
(
BaseDateTimeFilter
,
self
)
.
__init__
(
name
,
super
(
BaseDateTimeFilter
,
self
)
.
__init__
(
name
,
options
,
options
,
...
@@ -51,6 +104,11 @@ class BaseDateTimeFilter(BaseFilter):
...
@@ -51,6 +104,11 @@ class BaseDateTimeFilter(BaseFilter):
def
convert
(
*
args
):
def
convert
(
*
args
):
"""
Decorator for field to filter conversion routine.
See :mod:`flask.ext.adminex.ext.sqlamodel.filters` for usage example.
"""
def
_inner
(
func
):
def
_inner
(
func
):
print
args
print
args
func
.
_converter_for
=
args
func
.
_converter_for
=
args
...
@@ -59,6 +117,12 @@ def convert(*args):
...
@@ -59,6 +117,12 @@ def convert(*args):
class
BaseFilterConverter
(
object
):
class
BaseFilterConverter
(
object
):
"""
Base filter converter.
Derive from this class to implement custom field to filter conversion
logic.
"""
def
__init__
(
self
):
def
__init__
(
self
):
self
.
converters
=
dict
()
self
.
converters
=
dict
()
...
...
flask_adminex/templates/admin/model/list.html
View file @
fedd6792
...
@@ -89,12 +89,12 @@
...
@@ -89,12 +89,12 @@
<tr>
<tr>
<td>
<td>
{%- if admin_view.can_edit -%}
{%- if admin_view.can_edit -%}
<a
class=
"icon"
href=
"{{ url_for('.edit_view', id=
row.id
, url=return_url) }}"
>
<a
class=
"icon"
href=
"{{ url_for('.edit_view', id=
get_pk_value(row)
, url=return_url) }}"
>
<i
class=
"icon-pencil"
></i>
<i
class=
"icon-pencil"
></i>
</a>
</a>
{%- endif -%}
{%- endif -%}
{%- if admin_view.can_delete -%}
{%- if admin_view.can_delete -%}
<form
class=
"icon"
method=
"POST"
action=
"{{ url_for('.delete_view', id=
row.id
, url=return_url) }}"
>
<form
class=
"icon"
method=
"POST"
action=
"{{ url_for('.delete_view', id=
get_pk_value(row)
, url=return_url) }}"
>
<button
onclick=
"return confirm('You sure you want to delete this item?')"
>
<button
onclick=
"return confirm('You sure you want to delete this item?')"
>
<i
class=
"icon-remove"
></i>
<i
class=
"icon-remove"
></i>
</button>
</button>
...
...
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