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
ac5fe084
Commit
ac5fe084
authored
Mar 02, 2015
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of github.com:mrjoes/flask-admin
parents
d4480885
1b36345c
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
714 additions
and
284 deletions
+714
-284
admin.pot
babel/admin.pot
+99
-98
__init__.py
flask_admin/contrib/appengine/__init__.py
+6
-0
view.py
flask_admin/contrib/appengine/view.py
+179
-0
fileadmin.py
flask_admin/contrib/fileadmin.py
+231
-98
view.py
flask_admin/contrib/sqla/view.py
+1
-6
helpers.py
flask_admin/helpers.py
+9
-4
base.py
flask_admin/model/base.py
+5
-7
list.html
flask_admin/templates/bootstrap2/admin/file/list.html
+4
-2
layout.html
flask_admin/templates/bootstrap2/admin/layout.html
+25
-27
inline_list_base.html
...in/templates/bootstrap2/admin/model/inline_list_base.html
+1
-1
list.html
flask_admin/templates/bootstrap3/admin/file/list.html
+4
-2
layout.html
flask_admin/templates/bootstrap3/admin/layout.html
+26
-25
inline_list_base.html
...in/templates/bootstrap3/admin/model/inline_list_base.html
+1
-1
test_fileadmin.py
flask_admin/tests/fileadmin/test_fileadmin.py
+109
-4
test_basic.py
flask_admin/tests/sqla/test_basic.py
+14
-9
No files found.
babel/admin.pot
View file @
ac5fe084
This diff is collapsed.
Click to expand it.
flask_admin/contrib/appengine/__init__.py
0 → 100644
View file @
ac5fe084
try
:
import
wtforms_appengine
except
ImportError
:
raise
Exception
(
'Please install wtforms_appengine in order to use appengine backend'
)
from
.view
import
ModelView
flask_admin/contrib/appengine/view.py
0 → 100644
View file @
ac5fe084
import
logging
from
flask.ext.admin.model
import
BaseModelView
from
wtforms_appengine
import
db
as
wt_db
from
wtforms_appengine
import
ndb
as
wt_ndb
from
google.appengine.ext
import
db
from
google.appengine.ext
import
ndb
class
NdbModelView
(
BaseModelView
):
"""
AppEngine NDB model scaffolding.
"""
def
get_pk_value
(
self
,
model
):
return
model
.
key
.
urlsafe
()
def
scaffold_list_columns
(
self
):
return
sorted
([
k
for
(
k
,
v
)
in
self
.
model
.
__dict__
.
iteritems
()
if
isinstance
(
v
,
ndb
.
Property
)])
def
scaffold_sortable_columns
(
self
):
return
[
k
for
(
k
,
v
)
in
self
.
model
.
__dict__
.
iteritems
()
if
isinstance
(
v
,
ndb
.
Property
)
and
v
.
_indexed
]
def
init_search
(
self
):
return
None
def
is_valid_filter
(
self
):
pass
def
scaffold_filters
(
self
):
#TODO: implement
pass
def
scaffold_form
(
self
):
return
wt_ndb
.
model_form
(
self
.
model
())
def
get_list
(
self
,
page
,
sort_field
,
sort_desc
,
search
,
filters
):
#TODO: implement filters (don't think search can work here)
q
=
self
.
model
.
query
()
if
sort_field
:
order_field
=
getattr
(
self
.
model
,
sort_field
)
if
sort_desc
:
order_field
=
-
order_field
q
=
q
.
order
(
order_field
)
results
=
q
.
fetch
(
self
.
page_size
,
offset
=
page
*
self
.
page_size
)
return
q
.
count
(),
results
def
get_one
(
self
,
urlsafe_key
):
return
ndb
.
Key
(
urlsafe
=
urlsafe_key
)
.
get
()
def
create_model
(
self
,
form
):
try
:
model
=
self
.
model
()
form
.
populate_obj
(
model
)
model
.
put
()
return
True
except
Exception
as
ex
:
if
not
self
.
handle_view_exception
(
ex
):
#flash(gettext('Failed to create record. %(error)s',
# error=ex), 'error')
logging
.
exception
(
'Failed to create record.'
)
return
False
def
update_model
(
self
,
form
,
model
):
try
:
form
.
populate_obj
(
model
)
model
.
put
()
return
True
except
Exception
as
ex
:
if
not
self
.
handle_view_exception
(
ex
):
#flash(gettext('Failed to update record. %(error)s',
# error=ex), 'error')
logging
.
exception
(
'Failed to update record.'
)
return
False
def
delete_model
(
self
,
model
):
try
:
model
.
key
.
delete
()
return
True
except
Exception
as
ex
:
if
not
self
.
handle_view_exception
(
ex
):
#flash(gettext('Failed to delete record. %(error)s',
# error=ex),
# 'error')
logging
.
exception
(
'Failed to delete record.'
)
return
False
class
DbModelView
(
BaseModelView
):
"""
AppEngine DB model scaffolding.
"""
def
get_pk_value
(
self
,
model
):
return
str
(
model
.
key
())
def
scaffold_list_columns
(
self
):
return
sorted
([
k
for
(
k
,
v
)
in
self
.
model
.
__dict__
.
iteritems
()
if
isinstance
(
v
,
db
.
Property
)])
def
scaffold_sortable_columns
(
self
):
return
[
k
for
(
k
,
v
)
in
self
.
model
.
__dict__
.
iteritems
()
if
isinstance
(
v
,
db
.
Property
)
and
v
.
_indexed
]
def
init_search
(
self
):
return
None
def
is_valid_filter
(
self
):
pass
def
scaffold_filters
(
self
):
#TODO: implement
pass
def
scaffold_form
(
self
):
return
wt_db
.
model_form
(
self
.
model
())
def
get_list
(
self
,
page
,
sort_field
,
sort_desc
,
search
,
filters
):
#TODO: implement filters (don't think search can work here)
q
=
self
.
model
.
all
()
if
sort_field
:
if
sort_desc
:
sort_field
=
"-"
+
sort_field
q
.
order
(
sort_field
)
results
=
q
.
fetch
(
self
.
page_size
,
offset
=
page
*
self
.
page_size
)
return
q
.
count
(),
results
def
get_one
(
self
,
encoded_key
):
return
db
.
get
(
db
.
Key
(
encoded
=
encoded_key
))
def
create_model
(
self
,
form
):
try
:
model
=
self
.
model
()
form
.
populate_obj
(
model
)
model
.
put
()
return
True
except
Exception
as
ex
:
if
not
self
.
handle_view_exception
(
ex
):
#flash(gettext('Failed to create record. %(error)s',
# error=ex), 'error')
logging
.
exception
(
'Failed to create record.'
)
return
False
def
update_model
(
self
,
form
,
model
):
try
:
form
.
populate_obj
(
model
)
model
.
put
()
return
True
except
Exception
as
ex
:
if
not
self
.
handle_view_exception
(
ex
):
#flash(gettext('Failed to update record. %(error)s',
# error=ex), 'error')
logging
.
exception
(
'Failed to update record.'
)
return
False
def
delete_model
(
self
,
model
):
try
:
model
.
delete
()
return
True
except
Exception
as
ex
:
if
not
self
.
handle_view_exception
(
ex
):
#flash(gettext('Failed to delete record. %(error)s',
# error=ex),
# 'error')
logging
.
exception
(
'Failed to delete record.'
)
return
False
def
ModelView
(
model
):
if
issubclass
(
model
,
ndb
.
Model
):
return
NdbModelView
(
model
)
elif
issubclass
(
model
,
db
.
Model
):
return
DbModelView
(
model
)
else
:
raise
ValueError
(
"Unsupported model:
%
s"
%
model
)
flask_admin/contrib/fileadmin.py
View file @
ac5fe084
This diff is collapsed.
Click to expand it.
flask_admin/contrib/sqla/view.py
View file @
ac5fe084
...
...
@@ -80,8 +80,7 @@ class ModelView(BaseModelView):
'searchable_columns'
,
None
)
"""
Collection of the searchable columns. Only text-based columns
are searchable (`String`, `Unicode`, `Text`, `UnicodeText`).
Collection of the searchable columns.
Example::
...
...
@@ -491,10 +490,6 @@ class ModelView(BaseModelView):
for
column
in
self
.
_get_columns_for_field
(
attr
):
column_type
=
type
(
column
.
type
)
.
__name__
if
not
self
.
is_text_column_type
(
column_type
):
raise
Exception
(
'Can only search on text columns. '
+
'Failed to setup search for "
%
s"'
%
p
)
self
.
_search_fields
.
append
(
column
)
# Store joins, avoid duplicates
...
...
flask_admin/helpers.py
View file @
ac5fe084
from
re
import
sub
from
jinja2
import
contextfunction
from
flask
import
g
,
request
,
url_for
from
flask
import
g
,
request
,
url_for
,
flash
from
wtforms.validators
import
DataRequired
,
InputRequired
from
flask.ext.admin._compat
import
urljoin
,
urlparse
from
flask.ext.admin._compat
import
urljoin
,
urlparse
,
iteritems
from
flask.ext.admin.babel
import
gettext
from
._compat
import
string_types
...
...
@@ -93,7 +93,12 @@ def is_field_error(errors):
return
True
return
False
def
flash_errors
(
form
,
message
):
for
field_name
,
errors
in
iteritems
(
form
.
errors
):
errors
=
form
[
field_name
]
.
label
.
text
+
u": "
+
u", "
.
join
(
errors
)
flash
(
gettext
(
message
,
error
=
str
(
errors
)),
'error'
)
@
contextfunction
def
resolve_ctx
(
context
):
...
...
flask_admin/model/base.py
View file @
ac5fe084
...
...
@@ -14,7 +14,7 @@ from flask.ext.admin.form import BaseForm, FormOpts, rules
from
flask.ext.admin.model
import
filters
,
typefmt
from
flask.ext.admin.actions
import
ActionsMixin
from
flask.ext.admin.helpers
import
(
get_form_data
,
validate_form_on_submit
,
get_redirect_target
)
get_redirect_target
,
flash_errors
)
from
flask.ext.admin.tools
import
rec_getattr
from
flask.ext.admin._backwards
import
ObsoleteAttr
from
flask.ext.admin._compat
import
iteritems
,
OrderedDict
,
as_unicode
...
...
@@ -972,6 +972,9 @@ class BaseModelView(BaseView, ActionsMixin):
Instantiate model delete form and return it.
Override to implement custom behavior.
The delete form originally used a GET request, so delete_form
accepts both GET and POST request for backwards compatibility.
"""
if
request
.
form
:
return
self
.
_delete_form_class
(
request
.
form
)
...
...
@@ -1558,12 +1561,7 @@ class BaseModelView(BaseView, ActionsMixin):
flash
(
gettext
(
'Record was successfully deleted.'
))
return
redirect
(
return_url
)
else
:
# flash validation errors
for
field_name
,
errors
in
iteritems
(
form
.
errors
):
errors
=
field_name
+
u": "
+
u", "
.
join
(
errors
)
flash
(
gettext
(
'Failed to delete record.
%(error)
s'
,
error
=
str
(
errors
)),
'error'
)
flash_errors
(
form
,
message
=
'Failed to delete record.
%(error)
s'
)
return
redirect
(
return_url
)
...
...
flask_admin/templates/bootstrap2/admin/file/list.html
View file @
ac5fe084
...
...
@@ -58,7 +58,8 @@
{% if is_dir %}
{% if name != '..' and admin_view.can_delete_dirs %}
<form
class=
"icon"
method=
"POST"
action=
"{{ get_url('.delete') }}"
>
<input
type=
"hidden"
name=
"path"
value=
"{{ path }}"
></input>
{{ delete_form.path(value=path) }}
{{ delete_form.csrf_token }}
<button
onclick=
"return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\' recursively?', name=name) }}')"
>
<i
class=
"icon-remove"
></i>
</button>
...
...
@@ -66,7 +67,8 @@
{% endif %}
{% else %}
<form
class=
"icon"
method=
"POST"
action=
"{{ get_url('.delete') }}"
>
<input
type=
"hidden"
name=
"path"
value=
"{{ path }}"
></input>
{{ delete_form.path(value=path) }}
{{ delete_form.csrf_token }}
<button
onclick=
"return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\'?', name=name) }}')"
>
<i
class=
"icon-remove"
></i>
</button>
...
...
flask_admin/templates/bootstrap2/admin/layout.html
View file @
ac5fe084
{% macro menu_icon(item) -%}
{% set icon_type = item.get_icon_type() %}
{% if icon_type %}
{%
-
if icon_type %}
{% set icon_value = item.get_icon_value() %}
{% if icon_type == 'glyph' %}
<i
class=
"{{ icon_value }}"
></i>
...
...
@@ -13,45 +13,43 @@
{%- endmacro %}
{% macro menu() %}
{% for item in admin_view.admin.menu() %}
{%
if item.is_category()
%}
{%
-
for item in admin_view.admin.menu() %}
{%
- if item.is_category() -
%}
{% set children = item.get_children() %}
{% if children %}
{%
-
if children %}
{% set class_name = item.get_class_name() %}
{% if item.is_active(admin_view) %}
{%
-
if item.is_active(admin_view) %}
<li
class=
"active dropdown{% if class_name %} {{class_name}}{% endif %}"
>
{% else %}
{% else
-
%}
<li
class=
"dropdown{% if class_name %} {{class_name}}{% endif %}"
>
{% endif %}
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"javascript:void(0)"
>
{{ menu_icon(item) }}{{ item.name }}
<b
class=
"caret"
></b>
</a>
{%- endif %}
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"javascript:void(0)"
>
{{ menu_icon(item) }}{{ item.name }}
<b
class=
"caret"
></b></a>
<ul
class=
"dropdown-menu"
>
{% for child in children
%}
{% set class_name = child.get_class_name() %}
{%
if child.is_active(admin_view) %}
<li
class=
"active{% if class_name %} {{class_name}}{% endif %}"
>
{% else %}
<li
{%
if
class_name
%}
class=
"{{class_name}}"
{%
endif
%}
>
{%
endif %}
<a
href=
"{{ child.get_url() }}"
>
{{ menu_icon(child) }}{{ child.name }}
</a>
</li>
{%
endfor %}
{%- for child in children -
%}
{% set class_name = child.get_class_name() %}
{%-
if child.is_active(admin_view) %}
<li
class=
"active{% if class_name %} {{class_name}}{% endif %}"
>
{% else %}
<li
{%
if
class_name
%}
class=
"{{class_name}}"
{%
endif
%}
>
{%-
endif %}
<a
href=
"{{ child.get_url() }}"
>
{{ menu_icon(child) }}{{ child.name }}
</a>
</li>
{%-
endfor %}
</ul>
</li>
{% endif %}
{% else %}
{%
if item.is_accessible() and item.is_visible()
%}
{%
-
else %}
{%
- if item.is_accessible() and item.is_visible() -
%}
{% set class_name = item.get_class_name() %}
{% if item.is_active(admin_view) %}
{%
-
if item.is_active(admin_view) %}
<li
class=
"active{% if class_name %} {{class_name}}{% endif %}"
>
{% else %}
{%
-
else %}
<li
{%
if
class_name
%}
class=
"{{class_name}}"
{%
endif
%}
>
{% endif %}
{%
-
endif %}
<a
href=
"{{ item.get_url() }}"
>
{{ menu_icon(item) }}{{ item.name }}
</a>
</li>
{%
endif
%}
{% endif %}
{%
- endif -
%}
{% endif
-
%}
{% endfor %}
{% endmacro %}
...
...
flask_admin/templates/bootstrap2/admin/model/inline_list_base.html
View file @
ac5fe084
{% macro render_inline_fields(field, template, render, check=None) %}
<div
class=
"inline-field"
>
<div
class=
"inline-field"
id=
"{{ field.id }}"
>
{# existing inline form fields #}
<div
class=
"inline-field-list"
>
{% for subfield in field %}
...
...
flask_admin/templates/bootstrap3/admin/file/list.html
View file @
ac5fe084
...
...
@@ -58,7 +58,8 @@
{% if is_dir %}
{% if name != '..' and admin_view.can_delete_dirs %}
<form
class=
"icon"
method=
"POST"
action=
"{{ get_url('.delete') }}"
>
<input
type=
"hidden"
name=
"path"
value=
"{{ path }}"
></input>
{{ delete_form.path(value=path) }}
{{ delete_form.csrf_token }}
<button
onclick=
"return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\' recursively?', name=name) }}')"
>
<i
class=
"glyphicon glyphicon-remove"
></i>
</button>
...
...
@@ -66,7 +67,8 @@
{% endif %}
{% else %}
<form
class=
"icon"
method=
"POST"
action=
"{{ get_url('.delete') }}"
>
<input
type=
"hidden"
name=
"path"
value=
"{{ path }}"
></input>
{{ delete_form.path(value=path) }}
{{ delete_form.csrf_token }}
<button
onclick=
"return confirm('{{ _gettext('Are you sure you want to delete \\\'%(name)s\\\'?', name=name) }}')"
>
<i
class=
"glyphicon glyphicon-trash"
></i>
</button>
...
...
flask_admin/templates/bootstrap3/admin/layout.html
View file @
ac5fe084
{% macro menu_icon(item) -%}
{% set icon_type = item.get_icon_type() %}
{% if icon_type %}
{%
-
if icon_type %}
{% set icon_value = item.get_icon_value() %}
{% if icon_type == 'glyph' %}
<i
class=
"glyphicon {{ icon_value }}"
></i>
...
...
@@ -13,42 +13,43 @@
{%- endmacro %}
{% macro menu() %}
{% for item in admin_view.admin.menu() %}
{%
if item.is_category()
%}
{%
-
for item in admin_view.admin.menu() %}
{%
- if item.is_category() -
%}
{% set children = item.get_children() %}
{% if children %}
{% if item.is_active(admin_view) %}
{%- if children %}
{% set class_name = item.get_class_name() %}
{%- if item.is_active(admin_view) %}
<li
class=
"active dropdown{% if class_name %} {{class_name}}{% endif %}"
>
{% else %}
{% else
-
%}
<li
class=
"dropdown{% if class_name %} {{class_name}}{% endif %}"
>
{% endif %}
{%
-
endif %}
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"javascript:void(0)"
>
{{ menu_icon(item) }}{{ item.name }}
<b
class=
"caret"
></b></a>
<ul
class=
"dropdown-menu"
>
{% for child in children
%}
{% set class_name = child.get_class_name() %}
{%
if child.is_active(admin_view) %}
<li
class=
"active"
{%
if
class_name
%}
{{
class_name
}}{%
endif
%}
>
{% else %}
<li
{%
if
class_name
%}
class=
"{{class_name}}"
{%
endif
%}
>
{%
endif %}
<a
href=
"{{ child.get_url() }}"
>
{{ menu_icon(child) }}{{ child.name }}
</a>
</li>
{%
endfor %}
{%- for child in children -
%}
{% set class_name = child.get_class_name() %}
{%-
if child.is_active(admin_view) %}
<li
class=
"active{% if class_name %} {{class_name}}{% endif %}"
>
{% else %}
<li
{%
if
class_name
%}
class=
"{{class_name}}"
{%
endif
%}
>
{%-
endif %}
<a
href=
"{{ child.get_url() }}"
>
{{ menu_icon(child) }}{{ child.name }}
</a>
</li>
{%-
endfor %}
</ul>
</li>
{% endif %}
{% else %}
{%
if item.is_accessible() and item.is_visible()
%}
{%
-
else %}
{%
- if item.is_accessible() and item.is_visible() -
%}
{% set class_name = item.get_class_name() %}
{% if item.is_active(admin_view) %}
<li
class=
"active
"
{%
if
class_name
%}
{{
class_name
}}{%
endif
%}
>
{% else %}
{%
-
if item.is_active(admin_view) %}
<li
class=
"active
{% if class_name %} {{class_name}}{% endif %}"
>
{%
-
else %}
<li
{%
if
class_name
%}
class=
"{{class_name}}"
{%
endif
%}
>
{% endif %}
{%
-
endif %}
<a
href=
"{{ item.get_url() }}"
>
{{ menu_icon(item) }}{{ item.name }}
</a>
</li>
{%
endif
%}
{% endif %}
{%
- endif -
%}
{% endif
-
%}
{% endfor %}
{% endmacro %}
...
...
flask_admin/templates/bootstrap3/admin/model/inline_list_base.html
View file @
ac5fe084
{% macro render_inline_fields(field, template, render, check=None) %}
<div
class=
"inline-field"
>
<div
class=
"inline-field"
id=
"{{ field.id }}"
>
{# existing inline form fields #}
<div
class=
"inline-field-list"
>
{% for subfield in field %}
...
...
flask_admin/tests/fileadmin/test_fileadmin.py
View file @
ac5fe084
from
nose.tools
import
eq_
,
ok_
import
os.path
as
op
from
nose.tools
import
eq_
,
ok_
from
flask.ext.admin.contrib
import
fileadmin
from
.
import
setup
try
:
from
StringIO
import
StringIO
except
ImportError
:
from
io
import
StringIO
def
create_view
():
app
,
admin
=
setup
()
class
MyFileAdmin
(
fileadmin
.
FileAdmin
):
editable_extensions
=
(
'txt'
,)
path
=
op
.
join
(
op
.
dirname
(
__file__
),
'files'
)
view
=
fileadmin
.
FileAdmin
(
path
,
'/files/'
,
name
=
'Files'
)
view
=
My
FileAdmin
(
path
,
'/files/'
,
name
=
'Files'
)
admin
.
add_view
(
view
)
return
app
,
admin
,
view
...
...
@@ -21,8 +30,104 @@ def test_file_admin():
client
=
app
.
test_client
()
rv
=
client
.
get
(
'/admin/fileadmin/'
)
# index
rv
=
client
.
get
(
'/admin/myfileadmin/'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'path=dummy.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
# edit
rv
=
client
.
get
(
'/admin/myfileadmin/edit/?path=dummy.txt'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'dummy.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
# TODO: Check actions, etc
rv
=
client
.
post
(
'/admin/myfileadmin/edit/?path=dummy.txt'
,
data
=
dict
(
content
=
'new_string'
))
eq_
(
rv
.
status_code
,
302
)
rv
=
client
.
get
(
'/admin/myfileadmin/edit/?path=dummy.txt'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'dummy.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
ok_
(
'new_string'
in
rv
.
data
.
decode
(
'utf-8'
))
# rename
rv
=
client
.
get
(
'/admin/myfileadmin/rename/?path=dummy.txt'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'dummy.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
rv
=
client
.
post
(
'/admin/myfileadmin/rename/?path=dummy.txt'
,
data
=
dict
(
name
=
'dummy_renamed.txt'
,
path
=
'dummy.txt'
))
eq_
(
rv
.
status_code
,
302
)
rv
=
client
.
get
(
'/admin/myfileadmin/'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'path=dummy_renamed.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
ok_
(
'path=dummy.txt'
not
in
rv
.
data
.
decode
(
'utf-8'
))
# upload
rv
=
client
.
get
(
'/admin/myfileadmin/upload/'
)
eq_
(
rv
.
status_code
,
200
)
rv
=
client
.
post
(
'/admin/myfileadmin/upload/'
,
data
=
dict
(
upload
=
(
StringIO
(
""
),
'dummy.txt'
),
))
eq_
(
rv
.
status_code
,
302
)
rv
=
client
.
get
(
'/admin/myfileadmin/'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'path=dummy.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
ok_
(
'path=dummy_renamed.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
# delete
rv
=
client
.
post
(
'/admin/myfileadmin/delete/'
,
data
=
dict
(
path
=
'dummy_renamed.txt'
))
eq_
(
rv
.
status_code
,
302
)
rv
=
client
.
get
(
'/admin/myfileadmin/'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'path=dummy_renamed.txt'
not
in
rv
.
data
.
decode
(
'utf-8'
))
ok_
(
'path=dummy.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
# mkdir
rv
=
client
.
get
(
'/admin/myfileadmin/mkdir/'
)
eq_
(
rv
.
status_code
,
200
)
rv
=
client
.
post
(
'/admin/myfileadmin/mkdir/'
,
data
=
dict
(
name
=
'dummy_dir'
))
eq_
(
rv
.
status_code
,
302
)
rv
=
client
.
get
(
'/admin/myfileadmin/'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'path=dummy.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
ok_
(
'path=dummy_dir'
in
rv
.
data
.
decode
(
'utf-8'
))
# rename - directory
rv
=
client
.
get
(
'/admin/myfileadmin/rename/?path=dummy_dir'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'dummy_dir'
in
rv
.
data
.
decode
(
'utf-8'
))
rv
=
client
.
post
(
'/admin/myfileadmin/rename/?path=dummy_dir'
,
data
=
dict
(
name
=
'dummy_renamed_dir'
,
path
=
'dummy_dir'
))
eq_
(
rv
.
status_code
,
302
)
rv
=
client
.
get
(
'/admin/myfileadmin/'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'path=dummy_renamed_dir'
in
rv
.
data
.
decode
(
'utf-8'
))
ok_
(
'path=dummy_dir'
not
in
rv
.
data
.
decode
(
'utf-8'
))
# delete - directory
rv
=
client
.
post
(
'/admin/myfileadmin/delete/'
,
data
=
dict
(
path
=
'dummy_renamed_dir'
))
eq_
(
rv
.
status_code
,
302
)
rv
=
client
.
get
(
'/admin/myfileadmin/'
)
eq_
(
rv
.
status_code
,
200
)
ok_
(
'path=dummy_renamed_dir'
not
in
rv
.
data
.
decode
(
'utf-8'
))
ok_
(
'path=dummy.txt'
in
rv
.
data
.
decode
(
'utf-8'
))
flask_admin/tests/sqla/test_basic.py
View file @
ac5fe084
...
...
@@ -253,27 +253,32 @@ def test_column_searchable_list():
Model1
,
Model2
=
create_models
(
db
)
view
=
CustomModelView
(
Model
1
,
db
.
session
,
column_searchable_list
=
[
'
test1'
,
'test2
'
])
view
=
CustomModelView
(
Model
2
,
db
.
session
,
column_searchable_list
=
[
'
string_field'
,
'int_field
'
])
admin
.
add_view
(
view
)
eq_
(
view
.
_search_supported
,
True
)
eq_
(
len
(
view
.
_search_fields
),
2
)
ok_
(
isinstance
(
view
.
_search_fields
[
0
],
db
.
Column
))
ok_
(
isinstance
(
view
.
_search_fields
[
1
],
db
.
Column
))
eq_
(
view
.
_search_fields
[
0
]
.
name
,
'
test1
'
)
eq_
(
view
.
_search_fields
[
1
]
.
name
,
'
test2
'
)
eq_
(
view
.
_search_fields
[
0
]
.
name
,
'
string_field
'
)
eq_
(
view
.
_search_fields
[
1
]
.
name
,
'
int_field
'
)
db
.
session
.
add
(
Model
1
(
'model1'
))
db
.
session
.
add
(
Model
1
(
'model2'
))
db
.
session
.
add
(
Model
2
(
'model1-test'
,
5000
))
db
.
session
.
add
(
Model
2
(
'model2-test'
,
9000
))
db
.
session
.
commit
()
client
=
app
.
test_client
()
rv
=
client
.
get
(
'/admin/model1/?search=model1'
)
rv
=
client
.
get
(
'/admin/model2/?search=model1'
)
data
=
rv
.
data
.
decode
(
'utf-8'
)
ok_
(
'model1-test'
in
data
)
ok_
(
'model2-test'
not
in
data
)
rv
=
client
.
get
(
'/admin/model2/?search=9000'
)
data
=
rv
.
data
.
decode
(
'utf-8'
)
ok_
(
'model1
'
in
data
)
ok_
(
'model2
'
not
in
data
)
ok_
(
'model1
-test'
not
in
data
)
ok_
(
'model2
-test'
in
data
)
def
test_complex_searchable_list
():
...
...
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