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
bd18251e
Commit
bd18251e
authored
Nov 27, 2012
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Renamed some model configuration properties
parent
8af30ade
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
145 additions
and
96 deletions
+145
-96
simple.py
examples/mongoengine/simple.py
+1
-1
simple.py
examples/peewee/simple.py
+3
-4
simple.py
examples/pymongo/simple.py
+5
-5
simple.py
examples/sqla/simple.py
+4
-5
view.py
flask_admin/contrib/mongoengine/view.py
+6
-9
view.py
flask_admin/contrib/peeweemodel/view.py
+2
-7
view.py
flask_admin/contrib/pymongo/view.py
+4
-4
form.py
flask_admin/contrib/sqlamodel/form.py
+4
-3
view.py
flask_admin/contrib/sqlamodel/view.py
+9
-11
base.py
flask_admin/model/base.py
+40
-32
test_basic.py
flask_admin/tests/sqlamodel/test_basic.py
+6
-6
test_model.py
flask_admin/tests/test_model.py
+9
-9
tools.py
flask_admin/tools.py
+52
-0
No files found.
examples/mongoengine/simple.py
View file @
bd18251e
...
@@ -62,7 +62,7 @@ class Post(db.Document):
...
@@ -62,7 +62,7 @@ class Post(db.Document):
class
UserView
(
ModelView
):
class
UserView
(
ModelView
):
column_filters
=
[
'name'
]
column_filters
=
[
'name'
]
searchable_columns
=
(
'name'
,
'password'
)
column_searchable_list
=
(
'name'
,
'password'
)
# Flask views
# Flask views
...
...
examples/peewee/simple.py
View file @
bd18251e
...
@@ -52,15 +52,14 @@ class UserAdmin(peeweemodel.ModelView):
...
@@ -52,15 +52,14 @@ class UserAdmin(peeweemodel.ModelView):
class
PostAdmin
(
peeweemodel
.
ModelView
):
class
PostAdmin
(
peeweemodel
.
ModelView
):
# Visible columns in the list view
# Visible columns in the list view
#list_columns = ('title', 'user')
column_exclude_list
=
[
'text'
]
excluded_list_columns
=
[
'text'
]
# List of columns that can be sorted. For 'user' column, use User.email as
# List of columns that can be sorted. For 'user' column, use User.email as
# a column.
# a column.
sortable_columns
=
(
'title'
,
(
'user'
,
User
.
email
),
'date'
)
column_sortable_list
=
(
'title'
,
(
'user'
,
User
.
email
),
'date'
)
# Full text search
# Full text search
searchable_columns
=
(
'title'
,
User
.
username
)
column_searchable_list
=
(
'title'
,
User
.
username
)
# Column filters
# Column filters
column_filters
=
(
'title'
,
column_filters
=
(
'title'
,
...
...
examples/pymongo/simple.py
View file @
bd18251e
...
@@ -39,8 +39,8 @@ class UserForm(wtf.Form):
...
@@ -39,8 +39,8 @@ class UserForm(wtf.Form):
class
UserView
(
ModelView
):
class
UserView
(
ModelView
):
list_columns
=
(
'name'
,
'email'
,
'password'
)
column_list
=
(
'name'
,
'email'
,
'password'
)
sortable_columns
=
(
'name'
,
'email'
,
'password'
)
column_sortable_list
=
(
'name'
,
'email'
,
'password'
)
form
=
UserForm
form
=
UserForm
...
@@ -53,15 +53,15 @@ class TweetForm(wtf.Form):
...
@@ -53,15 +53,15 @@ class TweetForm(wtf.Form):
class
TweetView
(
ModelView
):
class
TweetView
(
ModelView
):
list_columns
=
(
'name'
,
'user_name'
,
'text'
)
column_list
=
(
'name'
,
'user_name'
,
'text'
)
sortable_columns
=
(
'name'
,
'text'
)
column_sortable_list
=
(
'name'
,
'text'
)
column_filters
=
(
filters
.
FilterEqual
(
'name'
,
'Name'
),
column_filters
=
(
filters
.
FilterEqual
(
'name'
,
'Name'
),
filters
.
FilterNotEqual
(
'name'
,
'Name'
),
filters
.
FilterNotEqual
(
'name'
,
'Name'
),
filters
.
FilterLike
(
'name'
,
'Name'
),
filters
.
FilterLike
(
'name'
,
'Name'
),
filters
.
FilterNotLike
(
'name'
,
'Name'
))
filters
.
FilterNotLike
(
'name'
,
'Name'
))
searchable_columns
=
(
'name'
,
'text'
)
column_searchable_list
=
(
'name'
,
'text'
)
form
=
TweetForm
form
=
TweetForm
...
...
examples/sqla/simple.py
View file @
bd18251e
...
@@ -85,17 +85,16 @@ class UserAdmin(sqlamodel.ModelView):
...
@@ -85,17 +85,16 @@ class UserAdmin(sqlamodel.ModelView):
# Customized Post model admin
# Customized Post model admin
class
PostAdmin
(
sqlamodel
.
ModelView
):
class
PostAdmin
(
sqlamodel
.
ModelView
):
# Visible columns in the list view
# Visible columns in the list view
#list_columns = ('title', 'user')
column_exclude_list
=
[
'text'
]
excluded_list_columns
=
[
'text'
]
# List of columns that can be sorted. For 'user' column, use User.username as
# List of columns that can be sorted. For 'user' column, use User.username as
# a column.
# a column.
sortable_columns
=
(
'title'
,
(
'user'
,
User
.
username
),
'date'
)
column_sortable_list
=
(
'title'
,
(
'user'
,
User
.
username
),
'date'
)
# Rename 'title' columns to 'Post Title' in list view
# Rename 'title' columns to 'Post Title' in list view
rename_column
s
=
dict
(
title
=
'Post Title'
)
column_label
s
=
dict
(
title
=
'Post Title'
)
searchable_columns
=
(
'title'
,
User
.
username
)
column_searchable_list
=
(
'title'
,
User
.
username
)
column_filters
=
(
'user'
,
column_filters
=
(
'user'
,
'title'
,
'title'
,
...
...
flask_admin/contrib/mongoengine/view.py
View file @
bd18251e
...
@@ -76,7 +76,7 @@ class ModelView(BaseModelView):
...
@@ -76,7 +76,7 @@ class ModelView(BaseModelView):
Override this attribute to use non-default converter.
Override this attribute to use non-default converter.
"""
"""
list
_type_formatters
=
MONGOENGINE_FORMATTERS
column
_type_formatters
=
MONGOENGINE_FORMATTERS
"""
"""
Customized type formatters for MongoEngine backend
Customized type formatters for MongoEngine backend
"""
"""
...
@@ -135,20 +135,17 @@ class ModelView(BaseModelView):
...
@@ -135,20 +135,17 @@ class ModelView(BaseModelView):
columns
=
[]
columns
=
[]
for
n
,
f
in
self
.
_get_model_fields
():
for
n
,
f
in
self
.
_get_model_fields
():
# Filter by name
if
(
self
.
excluded_list_columns
and
n
in
self
.
excluded_list_columns
):
continue
# Verify type
# Verify type
field_class
=
type
(
f
)
field_class
=
type
(
f
)
if
(
field_class
==
mongoengine
.
ListField
and
if
(
field_class
==
mongoengine
.
ListField
and
isinstance
(
f
.
field
,
mongoengine
.
EmbeddedDocumentField
)):
isinstance
(
f
.
field
,
mongoengine
.
EmbeddedDocumentField
)):
continue
continue
if
field_class
==
mongoengine
.
EmbeddedDocumentField
:
if
field_class
==
mongoengine
.
EmbeddedDocumentField
:
continue
continue
elif
self
.
list_display_pk
or
field_class
!=
mongoengine
.
ObjectIdField
:
if
self
.
list_display_pk
or
field_class
!=
mongoengine
.
ObjectIdField
:
columns
.
append
(
n
)
columns
.
append
(
n
)
return
columns
return
columns
...
@@ -170,8 +167,8 @@ class ModelView(BaseModelView):
...
@@ -170,8 +167,8 @@ class ModelView(BaseModelView):
"""
"""
Init search
Init search
"""
"""
if
self
.
searchable_columns
:
if
self
.
column_searchable_list
:
for
p
in
self
.
searchable_columns
:
for
p
in
self
.
column_searchable_list
:
if
isinstance
(
p
,
basestring
):
if
isinstance
(
p
,
basestring
):
p
=
self
.
model
.
_fields
.
get
(
p
)
p
=
self
.
model
.
_fields
.
get
(
p
)
...
...
flask_admin/contrib/peeweemodel/view.py
View file @
bd18251e
...
@@ -130,11 +130,6 @@ class ModelView(BaseModelView):
...
@@ -130,11 +130,6 @@ class ModelView(BaseModelView):
columns
=
[]
columns
=
[]
for
n
,
f
in
self
.
_get_model_fields
():
for
n
,
f
in
self
.
_get_model_fields
():
# Filter by name
if
(
self
.
excluded_list_columns
and
n
in
self
.
excluded_list_columns
):
continue
# Verify type
# Verify type
field_class
=
type
(
f
)
field_class
=
type
(
f
)
...
@@ -155,8 +150,8 @@ class ModelView(BaseModelView):
...
@@ -155,8 +150,8 @@ class ModelView(BaseModelView):
return
columns
return
columns
def
init_search
(
self
):
def
init_search
(
self
):
if
self
.
searchable_columns
:
if
self
.
column_searchable_list
:
for
p
in
self
.
searchable_columns
:
for
p
in
self
.
column_searchable_list
:
if
isinstance
(
p
,
basestring
):
if
isinstance
(
p
,
basestring
):
p
=
getattr
(
self
.
model
,
p
)
p
=
getattr
(
self
.
model
,
p
)
...
...
flask_admin/contrib/pymongo/view.py
View file @
bd18251e
...
@@ -86,8 +86,8 @@ class ModelView(BaseModelView):
...
@@ -86,8 +86,8 @@ class ModelView(BaseModelView):
"""
"""
Init search
Init search
"""
"""
if
self
.
searchable_columns
:
if
self
.
column_searchable_list
:
for
p
in
self
.
searchable_columns
:
for
p
in
self
.
column_searchable_list
:
if
not
isinstance
(
p
,
basestring
):
if
not
isinstance
(
p
,
basestring
):
raise
ValueError
(
'Expected string'
)
raise
ValueError
(
'Expected string'
)
...
@@ -130,13 +130,13 @@ class ModelView(BaseModelView):
...
@@ -130,13 +130,13 @@ class ModelView(BaseModelView):
:param name:
:param name:
Field name
Field name
"""
"""
column_fmt
=
self
.
list
_formatters
.
get
(
name
)
column_fmt
=
self
.
column
_formatters
.
get
(
name
)
if
column_fmt
is
not
None
:
if
column_fmt
is
not
None
:
return
column_fmt
(
context
,
model
,
name
)
return
column_fmt
(
context
,
model
,
name
)
value
=
model
.
get
(
name
)
value
=
model
.
get
(
name
)
type_fmt
=
self
.
list
_type_formatters
.
get
(
type
(
value
))
type_fmt
=
self
.
column
_type_formatters
.
get
(
type
(
value
))
if
type_fmt
is
not
None
:
if
type_fmt
is
not
None
:
value
=
type_fmt
(
value
)
value
=
type_fmt
(
value
)
...
...
flask_admin/contrib/sqlamodel/form.py
View file @
bd18251e
...
@@ -2,6 +2,7 @@ from wtforms import fields, validators
...
@@ -2,6 +2,7 @@ from wtforms import fields, validators
from
sqlalchemy
import
Boolean
,
Column
from
sqlalchemy
import
Boolean
,
Column
from
flask.ext.admin
import
form
from
flask.ext.admin
import
form
from
flask.ext.admin.tools
import
get_property
from
flask.ext.admin.model.form
import
(
converts
,
ModelConverterBase
,
from
flask.ext.admin.model.form
import
(
converts
,
ModelConverterBase
,
InlineFormAdmin
,
InlineModelConverterBase
)
InlineFormAdmin
,
InlineModelConverterBase
)
...
@@ -23,10 +24,10 @@ class AdminModelConverter(ModelConverterBase):
...
@@ -23,10 +24,10 @@ class AdminModelConverter(ModelConverterBase):
if
'label'
in
field_args
:
if
'label'
in
field_args
:
return
field_args
[
'label'
]
return
field_args
[
'label'
]
rename_columns
=
getattr
(
self
.
view
,
'rename_columns'
,
None
)
column_labels
=
get_property
(
self
.
view
,
'column_labels'
,
'rename_columns'
)
if
rename_column
s
:
if
column_label
s
:
return
rename_column
s
.
get
(
name
)
return
column_label
s
.
get
(
name
)
return
None
return
None
...
...
flask_admin/contrib/sqlamodel/view.py
View file @
bd18251e
...
@@ -7,6 +7,7 @@ from sqlalchemy import or_, Column
...
@@ -7,6 +7,7 @@ from sqlalchemy import or_, Column
from
flask
import
flash
from
flask
import
flash
from
flask.ext.admin.tools
import
ObsoleteAttr
from
flask.ext.admin.babel
import
gettext
,
ngettext
,
lazy_gettext
from
flask.ext.admin.babel
import
gettext
,
ngettext
,
lazy_gettext
from
flask.ext.admin.model
import
BaseModelView
from
flask.ext.admin.model
import
BaseModelView
from
flask.ext.admin.actions
import
action
from
flask.ext.admin.actions
import
action
...
@@ -63,7 +64,9 @@ class ModelView(BaseModelView):
...
@@ -63,7 +64,9 @@ class ModelView(BaseModelView):
Controls if list view should display all relations, not only many-to-one.
Controls if list view should display all relations, not only many-to-one.
"""
"""
searchable_columns
=
None
column_searchable_list
=
ObsoleteAttr
(
'column_searchable_list'
,
'searchable_columns'
,
None
)
"""
"""
Collection of the searchable columns. Only text-based columns
Collection of the searchable columns. Only text-based columns
are searchable (`String`, `Unicode`, `Text`, `UnicodeText`).
are searchable (`String`, `Unicode`, `Text`, `UnicodeText`).
...
@@ -71,12 +74,12 @@ class ModelView(BaseModelView):
...
@@ -71,12 +74,12 @@ class ModelView(BaseModelView):
Example::
Example::
class MyModelView(ModelView):
class MyModelView(ModelView):
searchable_columns
= ('name', 'email')
column_searchable_list
= ('name', 'email')
You can also pass columns::
You can also pass columns::
class MyModelView(ModelView):
class MyModelView(ModelView):
searchable_columns
= (User.name, User.email)
column_searchable_list
= (User.name, User.email)
Following search rules apply:
Following search rules apply:
...
@@ -253,11 +256,6 @@ class ModelView(BaseModelView):
...
@@ -253,11 +256,6 @@ class ModelView(BaseModelView):
columns
=
[]
columns
=
[]
for
p
in
self
.
_get_model_iterator
():
for
p
in
self
.
_get_model_iterator
():
# Filter by name
if
(
self
.
excluded_list_columns
and
p
.
key
in
self
.
excluded_list_columns
):
continue
# Verify type
# Verify type
if
hasattr
(
p
,
'direction'
):
if
hasattr
(
p
,
'direction'
):
if
self
.
list_display_all_relations
or
p
.
direction
.
name
==
'MANYTOONE'
:
if
self
.
list_display_all_relations
or
p
.
direction
.
name
==
'MANYTOONE'
:
...
@@ -329,11 +327,11 @@ class ModelView(BaseModelView):
...
@@ -329,11 +327,11 @@ class ModelView(BaseModelView):
For SQLAlchemy, this will initialize internal fields: list of
For SQLAlchemy, this will initialize internal fields: list of
column objects used for filtering, etc.
column objects used for filtering, etc.
"""
"""
if
self
.
searchable_columns
:
if
self
.
column_searchable_list
:
self
.
_search_fields
=
[]
self
.
_search_fields
=
[]
self
.
_search_joins
=
dict
()
self
.
_search_joins
=
dict
()
for
p
in
self
.
searchable_columns
:
for
p
in
self
.
column_searchable_list
:
for
column
in
self
.
_get_columns_for_field
(
p
):
for
column
in
self
.
_get_columns_for_field
(
p
):
column_type
=
type
(
column
.
type
)
.
__name__
column_type
=
type
(
column
.
type
)
.
__name__
...
@@ -347,7 +345,7 @@ class ModelView(BaseModelView):
...
@@ -347,7 +345,7 @@ class ModelView(BaseModelView):
if
column
.
table
!=
self
.
model
.
__table__
:
if
column
.
table
!=
self
.
model
.
__table__
:
self
.
_search_joins
[
column
.
table
.
name
]
=
column
.
table
self
.
_search_joins
[
column
.
table
.
name
]
=
column
.
table
return
bool
(
self
.
searchable_columns
)
return
bool
(
self
.
column_searchable_list
)
def
is_text_column_type
(
self
,
name
):
def
is_text_column_type
(
self
,
name
):
"""
"""
...
...
flask_admin/model/base.py
View file @
bd18251e
...
@@ -5,7 +5,7 @@ from jinja2 import contextfunction
...
@@ -5,7 +5,7 @@ from jinja2 import contextfunction
from
flask.ext.admin.babel
import
gettext
from
flask.ext.admin.babel
import
gettext
from
flask.ext.admin.base
import
BaseView
,
expose
from
flask.ext.admin.base
import
BaseView
,
expose
from
flask.ext.admin.tools
import
rec_getattr
from
flask.ext.admin.tools
import
rec_getattr
,
ObsoleteAttr
from
flask.ext.admin.model
import
filters
,
typefmt
from
flask.ext.admin.model
import
filters
,
typefmt
from
flask.ext.admin.actions
import
ActionsMixin
from
flask.ext.admin.actions
import
ActionsMixin
...
@@ -28,7 +28,6 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -28,7 +28,6 @@ class BaseModelView(BaseView, ActionsMixin):
2. Implement various data-related methods (`get_list`, `get_one`, `create_model`, etc)
2. Implement various data-related methods (`get_list`, `get_one`, `create_model`, etc)
3. Implement automatic form generation from the model representation (`scaffold_form`)
3. Implement automatic form generation from the model representation (`scaffold_form`)
"""
"""
# Permissions
# Permissions
can_create
=
True
can_create
=
True
"""Is model creation allowed"""
"""Is model creation allowed"""
...
@@ -50,7 +49,7 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -50,7 +49,7 @@ class BaseModelView(BaseView, ActionsMixin):
"""Default create template"""
"""Default create template"""
# Customizations
# Customizations
list_columns
=
None
column_list
=
ObsoleteAttr
(
'column_list'
,
'list_columns'
,
None
)
"""
"""
Collection of the model field names for the list view.
Collection of the model field names for the list view.
If set to `None`, will get them from the model.
If set to `None`, will get them from the model.
...
@@ -58,20 +57,21 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -58,20 +57,21 @@ class BaseModelView(BaseView, ActionsMixin):
For example::
For example::
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
list_columns
= ('name', 'last_name', 'email')
column_list
= ('name', 'last_name', 'email')
"""
"""
excluded_list_columns
=
None
column_exclude_list
=
ObsoleteAttr
(
'column_exclude_list'
,
'excluded_list_columns'
,
None
)
"""
"""
Collection of excluded list column names.
Collection of excluded list column names.
For example::
For example::
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
excluded_list_columns
= ('last_name', 'email')
column_exclude_list
= ('last_name', 'email')
"""
"""
list_formatters
=
dict
(
)
column_formatters
=
ObsoleteAttr
(
'column_formatters'
,
'list_formatters'
,
dict
()
)
"""
"""
Dictionary of list view column formatters.
Dictionary of list view column formatters.
...
@@ -79,7 +79,7 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -79,7 +79,7 @@ class BaseModelView(BaseView, ActionsMixin):
two, you can do something like this::
two, you can do something like this::
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
list
_formatters = dict(price=lambda c, m, p: m.price*2)
column
_formatters = dict(price=lambda c, m, p: m.price*2)
Callback function has following prototype::
Callback function has following prototype::
...
@@ -90,7 +90,7 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -90,7 +90,7 @@ class BaseModelView(BaseView, ActionsMixin):
pass
pass
"""
"""
list_type_formatters
=
None
column_type_formatters
=
ObsoleteAttr
(
'column_type_formatters'
,
'list_type_formatters'
,
None
)
"""
"""
Dictionary of value type formatters to be used in list view.
Dictionary of value type formatters to be used in list view.
...
@@ -102,7 +102,7 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -102,7 +102,7 @@ class BaseModelView(BaseView, ActionsMixin):
applied, just override this property with empty dictionary::
applied, just override this property with empty dictionary::
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
list
_type_formatters = dict()
column
_type_formatters = dict()
If you want to display `NULL` instead of empty string, you can do
If you want to display `NULL` instead of empty string, you can do
something like this::
something like this::
...
@@ -114,22 +114,24 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -114,22 +114,24 @@ class BaseModelView(BaseView, ActionsMixin):
})
})
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
list
_type_formatters = MY_DEFAULT_FORMATTERS
column
_type_formatters = MY_DEFAULT_FORMATTERS
Type formatters have lower priority than list column formatters.
Type formatters have lower priority than list column formatters.
"""
"""
rename_columns
=
None
column_labels
=
ObsoleteAttr
(
'column_labels'
,
'rename_columns'
,
None
)
"""
"""
Dictionary where key is column name and value is string to display.
Dictionary where key is column name and value is string to display.
For example::
For example::
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
rename_column
s = dict(name='Name', last_name='Last Name')
column_label
s = dict(name='Name', last_name='Last Name')
"""
"""
sortable_columns
=
None
column_sortable_list
=
ObsoleteAttr
(
'column_sortable_list'
,
'sortable_columns'
,
None
)
"""
"""
Collection of the sortable columns for the list view.
Collection of the sortable columns for the list view.
If set to `None`, will get them from the model.
If set to `None`, will get them from the model.
...
@@ -137,22 +139,24 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -137,22 +139,24 @@ class BaseModelView(BaseView, ActionsMixin):
For example::
For example::
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
sortable_columns
= ('name', 'last_name')
column_sortable_list
= ('name', 'last_name')
If you want to explicitly specify field/column to be used while
If you want to explicitly specify field/column to be used while
sorting, you can use tuple::
sorting, you can use tuple::
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
sortable_columns
= ('name', ('user', 'user.username'))
column_sortable_list
= ('name', ('user', 'user.username'))
When using SQLAlchemy models, model attributes can be used instead
When using SQLAlchemy models, model attributes can be used instead
of the string::
of the string::
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
sortable_columns
= ('name', ('user', User.username))
column_sortable_list
= ('name', ('user', User.username))
"""
"""
searchable_columns
=
None
column_searchable_list
=
ObsoleteAttr
(
'column_searchable_list'
,
'searchable_columns'
,
None
)
"""
"""
Collection of the searchable columns. It is assumed that only
Collection of the searchable columns. It is assumed that only
text-only fields are searchable, but it is up for a model
text-only fields are searchable, but it is up for a model
...
@@ -161,7 +165,7 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -161,7 +165,7 @@ class BaseModelView(BaseView, ActionsMixin):
Example::
Example::
class MyModelView(BaseModelView):
class MyModelView(BaseModelView):
searchable_columns
= ('name', 'email')
column_searchable_list
= ('name', 'email')
"""
"""
column_filters
=
None
column_filters
=
None
...
@@ -311,8 +315,8 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -311,8 +315,8 @@ class BaseModelView(BaseView, ActionsMixin):
self
.
_filters
=
self
.
get_filters
()
self
.
_filters
=
self
.
get_filters
()
# Type formatters
# Type formatters
if
self
.
list
_type_formatters
is
None
:
if
self
.
column
_type_formatters
is
None
:
self
.
list
_type_formatters
=
dict
(
typefmt
.
DEFAULT_FORMATTERS
)
self
.
column
_type_formatters
=
dict
(
typefmt
.
DEFAULT_FORMATTERS
)
if
self
.
_filters
:
if
self
.
_filters
:
self
.
_filter_groups
=
[]
self
.
_filter_groups
=
[]
...
@@ -362,21 +366,25 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -362,21 +366,25 @@ class BaseModelView(BaseView, ActionsMixin):
:param field:
:param field:
Model field name.
Model field name.
"""
"""
if
self
.
rename_columns
and
field
in
self
.
rename_column
s
:
if
self
.
column_labels
and
field
in
self
.
column_label
s
:
return
self
.
rename_column
s
[
field
]
return
self
.
column_label
s
[
field
]
else
:
else
:
return
self
.
prettify_name
(
field
)
return
self
.
prettify_name
(
field
)
def
get_list_columns
(
self
):
def
get_list_columns
(
self
):
"""
"""
Returns list of the model field names. If `
list_columns
` was
Returns list of the model field names. If `
column_list
` was
set, returns it. Otherwise calls `scaffold_list_columns`
set, returns it. Otherwise calls `scaffold_list_columns`
to generate list from the model.
to generate list from the model.
"""
"""
if
self
.
list_columns
is
None
:
columns
=
self
.
column_list
if
columns
is
None
:
columns
=
self
.
scaffold_list_columns
()
columns
=
self
.
scaffold_list_columns
()
else
:
columns
=
self
.
list_columns
# Filter excluded columns
if
self
.
column_exclude_list
:
columns
=
[
c
for
c
in
columns
if
c
not
in
self
.
column_exclude_list
]
return
[(
c
,
self
.
get_column_name
(
c
))
for
c
in
columns
]
return
[(
c
,
self
.
get_column_name
(
c
))
for
c
in
columns
]
...
@@ -395,15 +403,15 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -395,15 +403,15 @@ class BaseModelView(BaseView, ActionsMixin):
Returns dictionary of the sortable columns. Key is a model
Returns dictionary of the sortable columns. Key is a model
field name and value is sort column (for example - attribute).
field name and value is sort column (for example - attribute).
If `
sortable_columns
` is set, will use it. Otherwise, will call
If `
column_sortable_list
` is set, will use it. Otherwise, will call
`scaffold_sortable_columns` to get them from the model.
`scaffold_sortable_columns` to get them from the model.
"""
"""
if
self
.
sortable_columns
is
None
:
if
self
.
column_sortable_list
is
None
:
return
self
.
scaffold_sortable_columns
()
or
dict
()
return
self
.
scaffold_sortable_columns
()
or
dict
()
else
:
else
:
result
=
dict
()
result
=
dict
()
for
c
in
self
.
sortable_columns
:
for
c
in
self
.
column_sortable_list
:
if
isinstance
(
c
,
tuple
):
if
isinstance
(
c
,
tuple
):
result
[
c
[
0
]]
=
c
[
1
]
result
[
c
[
0
]]
=
c
[
1
]
else
:
else
:
...
@@ -740,13 +748,13 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -740,13 +748,13 @@ class BaseModelView(BaseView, ActionsMixin):
:param name:
:param name:
Field name
Field name
"""
"""
column_fmt
=
self
.
list
_formatters
.
get
(
name
)
column_fmt
=
self
.
column
_formatters
.
get
(
name
)
if
column_fmt
is
not
None
:
if
column_fmt
is
not
None
:
return
column_fmt
(
context
,
model
,
name
)
return
column_fmt
(
context
,
model
,
name
)
value
=
rec_getattr
(
model
,
name
)
value
=
rec_getattr
(
model
,
name
)
type_fmt
=
self
.
list
_type_formatters
.
get
(
type
(
value
))
type_fmt
=
self
.
column
_type_formatters
.
get
(
type
(
value
))
if
type_fmt
is
not
None
:
if
type_fmt
is
not
None
:
value
=
type_fmt
(
value
)
value
=
type_fmt
(
value
)
...
...
flask_admin/tests/sqlamodel/test_basic.py
View file @
bd18251e
...
@@ -132,8 +132,8 @@ def test_list_columns():
...
@@ -132,8 +132,8 @@ def test_list_columns():
Model1
,
Model2
=
create_models
(
db
)
Model1
,
Model2
=
create_models
(
db
)
view
=
CustomModelView
(
Model1
,
db
.
session
,
view
=
CustomModelView
(
Model1
,
db
.
session
,
list_columns
=
[
'test1'
,
'test3'
],
column_list
=
[
'test1'
,
'test3'
],
rename_column
s
=
dict
(
test1
=
'Column1'
))
column_label
s
=
dict
(
test1
=
'Column1'
))
admin
.
add_view
(
view
)
admin
.
add_view
(
view
)
eq_
(
len
(
view
.
_list_columns
),
2
)
eq_
(
len
(
view
.
_list_columns
),
2
)
...
@@ -152,7 +152,7 @@ def test_exclude_columns():
...
@@ -152,7 +152,7 @@ def test_exclude_columns():
Model1
,
Model2
=
create_models
(
db
)
Model1
,
Model2
=
create_models
(
db
)
view
=
CustomModelView
(
Model1
,
db
.
session
,
view
=
CustomModelView
(
Model1
,
db
.
session
,
excluded_list_columns
=
[
'test2'
,
'test4'
])
column_exclude_list
=
[
'test2'
,
'test4'
])
admin
.
add_view
(
view
)
admin
.
add_view
(
view
)
eq_
(
view
.
_list_columns
,
[(
'test1'
,
'Test1'
),
(
'test3'
,
'Test3'
)])
eq_
(
view
.
_list_columns
,
[(
'test1'
,
'Test1'
),
(
'test3'
,
'Test3'
)])
...
@@ -164,13 +164,13 @@ def test_exclude_columns():
...
@@ -164,13 +164,13 @@ def test_exclude_columns():
ok_
(
'Test2'
not
in
rv
.
data
)
ok_
(
'Test2'
not
in
rv
.
data
)
def
test_
searchable_columns
():
def
test_
column_searchable_list
():
app
,
db
,
admin
=
setup
()
app
,
db
,
admin
=
setup
()
Model1
,
Model2
=
create_models
(
db
)
Model1
,
Model2
=
create_models
(
db
)
view
=
CustomModelView
(
Model1
,
db
.
session
,
view
=
CustomModelView
(
Model1
,
db
.
session
,
searchable_columns
=
[
'test1'
,
'test2'
])
column_searchable_list
=
[
'test1'
,
'test2'
])
admin
.
add_view
(
view
)
admin
.
add_view
(
view
)
eq_
(
view
.
_search_supported
,
True
)
eq_
(
view
.
_search_supported
,
True
)
...
@@ -241,7 +241,7 @@ def test_url_args():
...
@@ -241,7 +241,7 @@ def test_url_args():
view
=
CustomModelView
(
Model1
,
db
.
session
,
view
=
CustomModelView
(
Model1
,
db
.
session
,
page_size
=
2
,
page_size
=
2
,
searchable_columns
=
[
'test1'
],
column_searchable_list
=
[
'test1'
],
column_filters
=
[
'test1'
])
column_filters
=
[
'test1'
])
admin
.
add_view
(
view
)
admin
.
add_view
(
view
)
...
...
flask_admin/tests/test_model.py
View file @
bd18251e
...
@@ -58,13 +58,13 @@ class MockModelView(base.BaseModelView):
...
@@ -58,13 +58,13 @@ class MockModelView(base.BaseModelView):
def
scaffold_list_columns
(
self
):
def
scaffold_list_columns
(
self
):
columns
=
[
'col1'
,
'col2'
,
'col3'
]
columns
=
[
'col1'
,
'col2'
,
'col3'
]
if
self
.
excluded_list_columns
:
if
self
.
column_exclude_list
:
return
filter
(
lambda
x
:
x
not
in
self
.
excluded_list_columns
,
columns
)
return
filter
(
lambda
x
:
x
not
in
self
.
column_exclude_list
,
columns
)
return
columns
return
columns
def
init_search
(
self
):
def
init_search
(
self
):
return
bool
(
self
.
searchable_columns
)
return
bool
(
self
.
column_searchable_list
)
def
scaffold_filters
(
self
,
name
):
def
scaffold_filters
(
self
,
name
):
return
[
SimpleFilter
(
name
)]
return
[
SimpleFilter
(
name
)]
...
@@ -222,8 +222,8 @@ def test_list_columns():
...
@@ -222,8 +222,8 @@ def test_list_columns():
app
,
admin
=
setup
()
app
,
admin
=
setup
()
view
=
MockModelView
(
Model
,
view
=
MockModelView
(
Model
,
list_columns
=
[
'col1'
,
'col3'
],
column_list
=
[
'col1'
,
'col3'
],
rename_column
s
=
dict
(
col1
=
'Column1'
))
column_label
s
=
dict
(
col1
=
'Column1'
))
admin
.
add_view
(
view
)
admin
.
add_view
(
view
)
eq_
(
len
(
view
.
_list_columns
),
2
)
eq_
(
len
(
view
.
_list_columns
),
2
)
...
@@ -239,7 +239,7 @@ def test_list_columns():
...
@@ -239,7 +239,7 @@ def test_list_columns():
def
test_exclude_columns
():
def
test_exclude_columns
():
app
,
admin
=
setup
()
app
,
admin
=
setup
()
view
=
MockModelView
(
Model
,
excluded_list_columns
=
[
'col2'
])
view
=
MockModelView
(
Model
,
column_exclude_list
=
[
'col2'
])
admin
.
add_view
(
view
)
admin
.
add_view
(
view
)
eq_
(
view
.
_list_columns
,
[(
'col1'
,
'Col1'
),
(
'col3'
,
'Col3'
)])
eq_
(
view
.
_list_columns
,
[(
'col1'
,
'Col1'
),
(
'col3'
,
'Col3'
)])
...
@@ -254,16 +254,16 @@ def test_exclude_columns():
...
@@ -254,16 +254,16 @@ def test_exclude_columns():
def
test_sortable_columns
():
def
test_sortable_columns
():
app
,
admin
=
setup
()
app
,
admin
=
setup
()
view
=
MockModelView
(
Model
,
sortable_columns
=
[
'col1'
,
(
'col2'
,
'test1'
)])
view
=
MockModelView
(
Model
,
column_sortable_list
=
[
'col1'
,
(
'col2'
,
'test1'
)])
admin
.
add_view
(
view
)
admin
.
add_view
(
view
)
eq_
(
view
.
_sortable_columns
,
dict
(
col1
=
'col1'
,
col2
=
'test1'
))
eq_
(
view
.
_sortable_columns
,
dict
(
col1
=
'col1'
,
col2
=
'test1'
))
def
test_
searchable_columns
():
def
test_
column_searchable_list
():
app
,
admin
=
setup
()
app
,
admin
=
setup
()
view
=
MockModelView
(
Model
,
searchable_columns
=
[
'col1'
,
'col2'
])
view
=
MockModelView
(
Model
,
column_searchable_list
=
[
'col1'
,
'col2'
])
admin
.
add_view
(
view
)
admin
.
add_view
(
view
)
eq_
(
view
.
_search_supported
,
True
)
eq_
(
view
.
_search_supported
,
True
)
...
...
flask_admin/tools.py
View file @
bd18251e
import
sys
import
sys
import
warnings
import
traceback
import
traceback
...
@@ -93,3 +94,54 @@ def get_dict_attr(obj, attr, default=None):
...
@@ -93,3 +94,54 @@ def get_dict_attr(obj, attr, default=None):
return
obj
.
__dict__
[
attr
]
return
obj
.
__dict__
[
attr
]
return
default
return
default
def
get_property
(
obj
,
name
,
old_name
,
default
=
None
):
"""
Check if old property name exists and if it is - show warning message
and return value.
Otherwise, return new property value
:param name:
New property name
:param old_name:
Old property name
:param default:
Default value
"""
if
hasattr
(
obj
,
old_name
):
warnings
.
warn
(
'Property
%
s is obsolete, please use
%
s instead'
%
(
old_name
,
name
),
stacklevel
=
2
)
return
getattr
(
obj
,
old_name
)
return
getattr
(
obj
,
name
,
default
)
class
ObsoleteAttr
(
object
):
def
__init__
(
self
,
new_name
,
old_name
,
default
):
self
.
new_name
=
new_name
self
.
old_name
=
old_name
self
.
cache
=
'_cache_'
+
new_name
self
.
default
=
default
def
__get__
(
self
,
obj
,
objtype
=
None
):
if
obj
is
None
:
return
self
# Check if we have new cached value
if
hasattr
(
obj
,
self
.
cache
):
return
getattr
(
obj
,
self
.
cache
)
# Check if there's old attribute
if
hasattr
(
obj
,
self
.
old_name
):
warnings
.
warn
(
'Property
%
s is obsolete, please use
%
s instead'
%
(
self
.
old_name
,
self
.
new_name
),
stacklevel
=
2
)
return
getattr
(
obj
,
self
.
old_name
)
# Return default otherwise
return
self
.
default
def
__set__
(
self
,
obj
,
value
):
print
'set'
,
self
.
new_name
,
value
,
self
.
cache
setattr
(
obj
,
self
.
cache
,
value
)
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