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
1b36345c
Commit
1b36345c
authored
Mar 01, 2015
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #800 from pawl/improvefileadmin
FileAdmin Improvements
parents
3c2b7122
8d690ae9
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
461 additions
and
215 deletions
+461
-215
admin.pot
babel/admin.pot
+99
-98
fileadmin.py
flask_admin/contrib/fileadmin.py
+231
-98
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
list.html
flask_admin/templates/bootstrap3/admin/file/list.html
+4
-2
test_fileadmin.py
flask_admin/tests/fileadmin/test_fileadmin.py
+109
-4
No files found.
babel/admin.pot
View file @
1b36345c
This diff is collapsed.
Click to expand it.
flask_admin/contrib/fileadmin.py
View file @
1b36345c
This diff is collapsed.
Click to expand it.
flask_admin/helpers.py
View file @
1b36345c
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 @
1b36345c
...
...
@@ -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 @
1b36345c
...
...
@@ -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/bootstrap3/admin/file/list.html
View file @
1b36345c
...
...
@@ -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/tests/fileadmin/test_fileadmin.py
View file @
1b36345c
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'
))
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