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
4ec6473a
Commit
4ec6473a
authored
Feb 27, 2014
by
bryhoyt
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #8 from mrjoes/master
Merge from central repo into bryhoyt's fork
parents
831a42c3
42d35970
Changes
18
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
270 additions
and
190 deletions
+270
-190
MANIFEST.in
MANIFEST.in
+1
-0
model_guidelines.rst
doc/model_guidelines.rst
+140
-144
auth.py
examples/auth/auth.py
+2
-2
simple.py
examples/sqla/simple.py
+6
-6
_compat.py
flask_admin/_compat.py
+2
-2
fileadmin.py
flask_admin/contrib/fileadmin.py
+31
-23
form.py
flask_admin/contrib/sqla/form.py
+2
-2
view.py
flask_admin/contrib/sqla/view.py
+4
-1
upload.py
flask_admin/form/upload.py
+5
-2
helpers.py
flask_admin/helpers.py
+17
-0
base.py
flask_admin/model/base.py
+7
-7
list.html
flask_admin/templates/admin/file/list.html
+1
-1
list.html
flask_admin/templates/admin/model/list.html
+2
-0
copyleft.gif
flask_admin/tests/data/copyleft.gif
+0
-0
copyleft.jpeg
flask_admin/tests/data/copyleft.jpeg
+0
-0
test_basic.py
flask_admin/tests/sqlamodel/test_basic.py
+23
-0
test_form_upload.py
flask_admin/tests/test_form_upload.py
+23
-0
admin.po
flask_admin/translations/ru/LC_MESSAGES/admin.po
+4
-0
No files found.
MANIFEST.in
View file @
4ec6473a
...
@@ -4,3 +4,4 @@ recursive-include flask_admin/static *
...
@@ -4,3 +4,4 @@ recursive-include flask_admin/static *
recursive-include flask_admin/templates *
recursive-include flask_admin/templates *
recursive-include flask_admin/translations *
recursive-include flask_admin/translations *
recursive-include flask_admin/tests *
recursive-include flask_admin/tests *
recursive-exclude flask_admin *.pyc
doc/model_guidelines.rst
View file @
4ec6473a
This diff is collapsed.
Click to expand it.
examples/auth/auth.py
View file @
4ec6473a
...
@@ -197,8 +197,8 @@ def build_sample_db():
...
@@ -197,8 +197,8 @@ def build_sample_db():
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
# Build a sample db on the fly, if one does not exist yet.
# Build a sample db on the fly, if one does not exist yet.
app_dir
=
o
p
.
realpath
(
os
.
path
.
dirname
(
__file__
))
app_dir
=
o
s
.
path
.
realpath
(
os
.
path
.
dirname
(
__file__
))
database_path
=
o
p
.
join
(
app_dir
,
app
.
config
[
'DATABASE_FILE'
])
database_path
=
o
s
.
path
.
join
(
app_dir
,
app
.
config
[
'DATABASE_FILE'
])
if
not
os
.
path
.
exists
(
database_path
):
if
not
os
.
path
.
exists
(
database_path
):
build_sample_db
()
build_sample_db
()
...
...
examples/sqla/simple.py
View file @
4ec6473a
...
@@ -31,8 +31,8 @@ class User(db.Model):
...
@@ -31,8 +31,8 @@ class User(db.Model):
username
=
db
.
Column
(
db
.
String
(
80
),
unique
=
True
)
username
=
db
.
Column
(
db
.
String
(
80
),
unique
=
True
)
email
=
db
.
Column
(
db
.
String
(
120
),
unique
=
True
)
email
=
db
.
Column
(
db
.
String
(
120
),
unique
=
True
)
# Required for administrative interface
# Required for administrative interface
. For python 3 please use __str__ instead.
def
__
str
__
(
self
):
def
__
unicode
__
(
self
):
return
self
.
username
return
self
.
username
...
@@ -54,7 +54,7 @@ class Post(db.Model):
...
@@ -54,7 +54,7 @@ class Post(db.Model):
tags
=
db
.
relationship
(
'Tag'
,
secondary
=
post_tags_table
)
tags
=
db
.
relationship
(
'Tag'
,
secondary
=
post_tags_table
)
def
__
str
__
(
self
):
def
__
unicode
__
(
self
):
return
self
.
title
return
self
.
title
...
@@ -62,7 +62,7 @@ class Tag(db.Model):
...
@@ -62,7 +62,7 @@ class Tag(db.Model):
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
)
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
)
name
=
db
.
Column
(
db
.
Unicode
(
64
))
name
=
db
.
Column
(
db
.
Unicode
(
64
))
def
__
str
__
(
self
):
def
__
unicode
__
(
self
):
return
self
.
name
return
self
.
name
...
@@ -75,7 +75,7 @@ class UserInfo(db.Model):
...
@@ -75,7 +75,7 @@ class UserInfo(db.Model):
user_id
=
db
.
Column
(
db
.
Integer
(),
db
.
ForeignKey
(
User
.
id
))
user_id
=
db
.
Column
(
db
.
Integer
(),
db
.
ForeignKey
(
User
.
id
))
user
=
db
.
relationship
(
User
,
backref
=
'info'
)
user
=
db
.
relationship
(
User
,
backref
=
'info'
)
def
__
str
__
(
self
):
def
__
unicode
__
(
self
):
return
'
%
s -
%
s'
%
(
self
.
key
,
self
.
value
)
return
'
%
s -
%
s'
%
(
self
.
key
,
self
.
value
)
...
@@ -85,7 +85,7 @@ class Tree(db.Model):
...
@@ -85,7 +85,7 @@ class Tree(db.Model):
parent_id
=
db
.
Column
(
db
.
Integer
,
db
.
ForeignKey
(
'tree.id'
))
parent_id
=
db
.
Column
(
db
.
Integer
,
db
.
ForeignKey
(
'tree.id'
))
parent
=
db
.
relationship
(
'Tree'
,
remote_side
=
[
id
],
backref
=
'children'
)
parent
=
db
.
relationship
(
'Tree'
,
remote_side
=
[
id
],
backref
=
'children'
)
def
__
str
__
(
self
):
def
__
unicode
__
(
self
):
return
self
.
name
return
self
.
name
...
...
flask_admin/_compat.py
View file @
4ec6473a
...
@@ -32,7 +32,7 @@ if not PY2:
...
@@ -32,7 +32,7 @@ if not PY2:
# Various tools
# Various tools
from
functools
import
reduce
from
functools
import
reduce
from
urllib.parse
import
urljoin
from
urllib.parse
import
urljoin
,
urlparse
else
:
else
:
text_type
=
unicode
text_type
=
unicode
string_types
=
(
str
,
unicode
)
string_types
=
(
str
,
unicode
)
...
@@ -50,7 +50,7 @@ else:
...
@@ -50,7 +50,7 @@ else:
# Helpers
# Helpers
reduce
=
__builtins__
[
'reduce'
]
if
isinstance
(
__builtins__
,
dict
)
else
__builtins__
.
reduce
reduce
=
__builtins__
[
'reduce'
]
if
isinstance
(
__builtins__
,
dict
)
else
__builtins__
.
reduce
from
urlparse
import
urljoin
from
urlparse
import
urljoin
,
urlparse
def
with_metaclass
(
meta
,
*
bases
):
def
with_metaclass
(
meta
,
*
bases
):
...
...
flask_admin/contrib/fileadmin.py
View file @
4ec6473a
...
@@ -155,6 +155,11 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -155,6 +155,11 @@ class FileAdmin(BaseView, ActionsMixin):
Edit template
Edit template
"""
"""
upload_form
=
UploadForm
"""
Upload form class
"""
def
__init__
(
self
,
base_path
,
base_url
=
None
,
def
__init__
(
self
,
base_path
,
base_url
=
None
,
name
=
None
,
category
=
None
,
endpoint
=
None
,
url
=
None
,
name
=
None
,
category
=
None
,
endpoint
=
None
,
url
=
None
,
verify_path
=
True
):
verify_path
=
True
):
...
@@ -285,7 +290,7 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -285,7 +290,7 @@ class FileAdmin(BaseView, ActionsMixin):
"""
"""
file_data
.
save
(
path
)
file_data
.
save
(
path
)
def
_get_dir_url
(
self
,
endpoint
,
path
,
**
kwargs
):
def
_get_dir_url
(
self
,
endpoint
,
path
=
None
,
**
kwargs
):
"""
"""
Return prettified URL
Return prettified URL
...
@@ -410,6 +415,17 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -410,6 +415,17 @@ class FileAdmin(BaseView, ActionsMixin):
"""
"""
pass
pass
def
_save_form_files
(
self
,
directory
,
path
,
form
):
filename
=
op
.
join
(
directory
,
secure_filename
(
form
.
upload
.
data
.
filename
))
if
op
.
exists
(
filename
):
flash
(
gettext
(
'File "
%(name)
s" already exists.'
,
name
=
filename
),
'error'
)
else
:
self
.
save_file
(
filename
,
form
.
upload
.
data
)
self
.
on_file_upload
(
directory
,
path
,
filename
)
@
expose
(
'/'
)
@
expose
(
'/'
)
@
expose
(
'/b/<path:path>'
)
@
expose
(
'/b/<path:path>'
)
def
index
(
self
,
path
=
None
):
def
index
(
self
,
path
=
None
):
...
@@ -423,7 +439,7 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -423,7 +439,7 @@ class FileAdmin(BaseView, ActionsMixin):
base_path
,
directory
,
path
=
self
.
_normalize_path
(
path
)
base_path
,
directory
,
path
=
self
.
_normalize_path
(
path
)
if
not
self
.
is_accessible_path
(
path
):
if
not
self
.
is_accessible_path
(
path
):
flash
(
gettext
(
gettext
(
'Permission denied.'
)
))
flash
(
gettext
(
'Permission denied.'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
# Get directory listing
# Get directory listing
...
@@ -486,24 +502,16 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -486,24 +502,16 @@ class FileAdmin(BaseView, ActionsMixin):
return
redirect
(
self
.
_get_dir_url
(
'.index'
,
path
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
,
path
))
if
not
self
.
is_accessible_path
(
path
):
if
not
self
.
is_accessible_path
(
path
):
flash
(
gettext
(
gettext
(
'Permission denied.'
)
))
flash
(
gettext
(
'Permission denied.'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
form
=
UploadF
orm
(
self
)
form
=
self
.
upload_f
orm
(
self
)
if
helpers
.
validate_form_on_submit
(
form
):
if
helpers
.
validate_form_on_submit
(
form
):
filename
=
op
.
join
(
directory
,
try
:
secure_filename
(
form
.
upload
.
data
.
filename
))
self
.
_save_form_files
(
directory
,
path
,
form
)
return
redirect
(
self
.
_get_dir_url
(
'.index'
,
path
))
if
op
.
exists
(
filename
):
except
Exception
as
ex
:
flash
(
gettext
(
'File "
%(name)
s" already exists.'
,
name
=
filename
),
flash
(
gettext
(
'Failed to save file:
%(error)
s'
,
error
=
ex
))
'error'
)
else
:
try
:
self
.
save_file
(
filename
,
form
.
upload
.
data
)
self
.
on_file_upload
(
directory
,
path
,
filename
)
return
redirect
(
self
.
_get_dir_url
(
'.index'
,
path
))
except
Exception
as
ex
:
flash
(
gettext
(
'Failed to save file:
%(error)
s'
,
error
=
ex
))
return
self
.
render
(
self
.
upload_template
,
form
=
form
)
return
self
.
render
(
self
.
upload_template
,
form
=
form
)
...
@@ -547,7 +555,7 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -547,7 +555,7 @@ class FileAdmin(BaseView, ActionsMixin):
return
redirect
(
dir_url
)
return
redirect
(
dir_url
)
if
not
self
.
is_accessible_path
(
path
):
if
not
self
.
is_accessible_path
(
path
):
flash
(
gettext
(
gettext
(
'Permission denied.'
)
))
flash
(
gettext
(
'Permission denied.'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
form
=
NameForm
(
helpers
.
get_form_data
())
form
=
NameForm
(
helpers
.
get_form_data
())
...
@@ -558,7 +566,7 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -558,7 +566,7 @@ class FileAdmin(BaseView, ActionsMixin):
self
.
on_mkdir
(
directory
,
form
.
name
.
data
)
self
.
on_mkdir
(
directory
,
form
.
name
.
data
)
return
redirect
(
dir_url
)
return
redirect
(
dir_url
)
except
Exception
as
ex
:
except
Exception
as
ex
:
flash
(
gettext
(
'Failed to create directory:
%(error)
s'
,
ex
),
'error'
)
flash
(
gettext
(
'Failed to create directory:
%(error)
s'
,
e
rror
=
e
x
),
'error'
)
return
self
.
render
(
self
.
mkdir_template
,
return
self
.
render
(
self
.
mkdir_template
,
form
=
form
,
form
=
form
,
...
@@ -584,7 +592,7 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -584,7 +592,7 @@ class FileAdmin(BaseView, ActionsMixin):
return
redirect
(
return_url
)
return
redirect
(
return_url
)
if
not
self
.
is_accessible_path
(
path
):
if
not
self
.
is_accessible_path
(
path
):
flash
(
gettext
(
gettext
(
'Permission denied.'
)
))
flash
(
gettext
(
'Permission denied.'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
if
op
.
isdir
(
full_path
):
if
op
.
isdir
(
full_path
):
...
@@ -627,7 +635,7 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -627,7 +635,7 @@ class FileAdmin(BaseView, ActionsMixin):
return
redirect
(
return_url
)
return
redirect
(
return_url
)
if
not
self
.
is_accessible_path
(
path
):
if
not
self
.
is_accessible_path
(
path
):
flash
(
gettext
(
gettext
(
'Permission denied.'
)
))
flash
(
gettext
(
'Permission denied.'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
if
not
op
.
exists
(
full_path
):
if
not
op
.
exists
(
full_path
):
...
@@ -672,8 +680,8 @@ class FileAdmin(BaseView, ActionsMixin):
...
@@ -672,8 +680,8 @@ class FileAdmin(BaseView, ActionsMixin):
base_path
,
full_path
,
path
=
self
.
_normalize_path
(
path
)
base_path
,
full_path
,
path
=
self
.
_normalize_path
(
path
)
if
not
self
.
is_accessible_path
(
path
):
if
not
self
.
is_accessible_path
(
path
)
or
not
self
.
is_file_editable
(
path
)
:
flash
(
gettext
(
gettext
(
'Permission denied.'
)
))
flash
(
gettext
(
'Permission denied.'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
return
redirect
(
self
.
_get_dir_url
(
'.index'
))
dir_url
=
self
.
_get_dir_url
(
'.index'
,
os
.
path
.
dirname
(
path
))
dir_url
=
self
.
_get_dir_url
(
'.index'
,
os
.
path
.
dirname
(
path
))
...
...
flask_admin/contrib/sqla/form.py
View file @
4ec6473a
...
@@ -106,9 +106,9 @@ class AdminModelConverter(ModelConverterBase):
...
@@ -106,9 +106,9 @@ class AdminModelConverter(ModelConverterBase):
kwargs
[
'label'
]
=
self
.
_get_label
(
prop
.
key
,
kwargs
)
kwargs
[
'label'
]
=
self
.
_get_label
(
prop
.
key
,
kwargs
)
kwargs
[
'description'
]
=
self
.
_get_description
(
prop
.
key
,
kwargs
)
kwargs
[
'description'
]
=
self
.
_get_description
(
prop
.
key
,
kwargs
)
if
column
.
nullable
:
if
column
.
nullable
or
prop
.
direction
.
name
!=
'MANYTOONE'
:
kwargs
[
'validators'
]
.
append
(
validators
.
Optional
())
kwargs
[
'validators'
]
.
append
(
validators
.
Optional
())
el
if
prop
.
direction
.
name
!=
'MANYTOMANY'
:
el
se
:
kwargs
[
'validators'
]
.
append
(
validators
.
InputRequired
())
kwargs
[
'validators'
]
.
append
(
validators
.
InputRequired
())
# Contribute model-related parameters
# Contribute model-related parameters
...
...
flask_admin/contrib/sqla/view.py
View file @
4ec6473a
...
@@ -428,7 +428,10 @@ class ModelView(BaseModelView):
...
@@ -428,7 +428,10 @@ class ModelView(BaseModelView):
:returns:
:returns:
``True`` for ``String``, ``Unicode``, ``Text``, ``UnicodeText``
``True`` for ``String``, ``Unicode``, ``Text``, ``UnicodeText``
"""
"""
return
name
in
(
'String'
,
'Unicode'
,
'Text'
,
'UnicodeText'
)
if
name
:
name
=
name
.
lower
()
return
name
in
(
'string'
,
'unicode'
,
'text'
,
'unicodetext'
)
def
scaffold_filters
(
self
,
name
):
def
scaffold_filters
(
self
,
name
):
"""
"""
...
...
flask_admin/form/upload.py
View file @
4ec6473a
...
@@ -177,7 +177,8 @@ class FileUploadField(fields.TextField):
...
@@ -177,7 +177,8 @@ class FileUploadField(fields.TextField):
return
True
return
True
return
(
'.'
in
filename
and
return
(
'.'
in
filename
and
filename
.
rsplit
(
'.'
,
1
)[
1
]
in
self
.
allowed_extensions
)
filename
.
rsplit
(
'.'
,
1
)[
1
]
.
lower
()
in
map
(
str
.
lower
,
self
.
allowed_extensions
))
def
pre_validate
(
self
,
form
):
def
pre_validate
(
self
,
form
):
if
(
self
.
data
and
if
(
self
.
data
and
...
@@ -208,6 +209,8 @@ class FileUploadField(fields.TextField):
...
@@ -208,6 +209,8 @@ class FileUploadField(fields.TextField):
filename
=
self
.
generate_name
(
obj
,
self
.
data
)
filename
=
self
.
generate_name
(
obj
,
self
.
data
)
filename
=
self
.
_save_file
(
self
.
data
,
filename
)
filename
=
self
.
_save_file
(
self
.
data
,
filename
)
# update filename of FileStorage to our validated name
self
.
data
.
filename
=
filename
setattr
(
obj
,
name
,
filename
)
setattr
(
obj
,
name
,
filename
)
...
@@ -329,7 +332,7 @@ class ImageUploadField(FileUploadField):
...
@@ -329,7 +332,7 @@ class ImageUploadField(FileUploadField):
"""
"""
# Check if PIL is installed
# Check if PIL is installed
if
Image
is
None
:
if
Image
is
None
:
raise
Exception
(
'PIL library was not found'
)
raise
ImportError
(
'PIL library was not found'
)
self
.
max_size
=
max_size
self
.
max_size
=
max_size
self
.
thumbnail_fn
=
thumbgen
or
thumbgen_filename
self
.
thumbnail_fn
=
thumbgen
or
thumbgen_filename
...
...
flask_admin/helpers.py
View file @
4ec6473a
...
@@ -3,6 +3,9 @@ from jinja2 import contextfunction
...
@@ -3,6 +3,9 @@ from jinja2 import contextfunction
from
flask
import
g
,
request
from
flask
import
g
,
request
from
wtforms.validators
import
DataRequired
,
InputRequired
from
wtforms.validators
import
DataRequired
,
InputRequired
from
flask.ext.admin._compat
import
urljoin
,
urlparse
from
._compat
import
string_types
from
._compat
import
string_types
...
@@ -96,3 +99,17 @@ def prettify_class_name(name):
...
@@ -96,3 +99,17 @@ def prettify_class_name(name):
String to split
String to split
"""
"""
return
sub
(
r'(?<=.)([A-Z])'
,
r' \1'
,
name
)
return
sub
(
r'(?<=.)([A-Z])'
,
r' \1'
,
name
)
def
is_safe_url
(
target
):
ref_url
=
urlparse
(
request
.
host_url
)
test_url
=
urlparse
(
urljoin
(
request
.
host_url
,
target
))
return
(
test_url
.
scheme
in
(
'http'
,
'https'
)
and
ref_url
.
netloc
==
test_url
.
netloc
)
def
get_redirect_target
(
param_name
=
'url'
):
target
=
request
.
values
.
get
(
param_name
)
if
target
and
is_safe_url
(
target
):
return
target
flask_admin/model/base.py
View file @
4ec6473a
...
@@ -11,7 +11,7 @@ from flask.ext.admin.base import BaseView, expose
...
@@ -11,7 +11,7 @@ from flask.ext.admin.base import BaseView, expose
from
flask.ext.admin.form
import
BaseForm
,
FormOpts
,
rules
from
flask.ext.admin.form
import
BaseForm
,
FormOpts
,
rules
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
from
flask.ext.admin.helpers
import
get_form_data
,
validate_form_on_submit
from
flask.ext.admin.helpers
import
get_form_data
,
validate_form_on_submit
,
get_redirect_target
from
flask.ext.admin.tools
import
rec_getattr
from
flask.ext.admin.tools
import
rec_getattr
from
flask.ext.admin._backwards
import
ObsoleteAttr
from
flask.ext.admin._backwards
import
ObsoleteAttr
from
flask.ext.admin._compat
import
iteritems
,
as_unicode
from
flask.ext.admin._compat
import
iteritems
,
as_unicode
...
@@ -1121,9 +1121,9 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -1121,9 +1121,9 @@ class BaseModelView(BaseView, ActionsMixin):
"""
"""
column_fmt
=
self
.
column_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
(
self
,
context
,
model
,
name
)
value
=
column_fmt
(
self
,
context
,
model
,
name
)
else
:
value
=
self
.
_get_field_value
(
model
,
name
)
value
=
self
.
_get_field_value
(
model
,
name
)
choices_map
=
self
.
_column_choices_map
.
get
(
name
,
{})
choices_map
=
self
.
_column_choices_map
.
get
(
name
,
{})
if
choices_map
:
if
choices_map
:
...
@@ -1250,7 +1250,7 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -1250,7 +1250,7 @@ class BaseModelView(BaseView, ActionsMixin):
"""
"""
Create model view
Create model view
"""
"""
return_url
=
request
.
args
.
get
(
'url'
)
or
url_for
(
'.index_view'
)
return_url
=
get_redirect_target
(
)
or
url_for
(
'.index_view'
)
if
not
self
.
can_create
:
if
not
self
.
can_create
:
return
redirect
(
return_url
)
return
redirect
(
return_url
)
...
@@ -1278,7 +1278,7 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -1278,7 +1278,7 @@ class BaseModelView(BaseView, ActionsMixin):
"""
"""
Edit model view
Edit model view
"""
"""
return_url
=
request
.
args
.
get
(
'url'
)
or
url_for
(
'.index_view'
)
return_url
=
get_redirect_target
(
)
or
url_for
(
'.index_view'
)
if
not
self
.
can_edit
:
if
not
self
.
can_edit
:
return
redirect
(
return_url
)
return
redirect
(
return_url
)
...
@@ -1316,7 +1316,7 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -1316,7 +1316,7 @@ class BaseModelView(BaseView, ActionsMixin):
"""
"""
Delete model view. Only POST method is allowed.
Delete model view. Only POST method is allowed.
"""
"""
return_url
=
request
.
args
.
get
(
'url'
)
or
url_for
(
'.index_view'
)
return_url
=
get_redirect_target
(
)
or
url_for
(
'.index_view'
)
# TODO: Use post
# TODO: Use post
if
not
self
.
can_delete
:
if
not
self
.
can_delete
:
...
...
flask_admin/templates/admin/file/list.html
View file @
4ec6473a
...
@@ -90,7 +90,7 @@
...
@@ -90,7 +90,7 @@
{% endif %}
{% endif %}
</td>
</td>
<td>
<td>
{{ size }}
{{ size
|filesizeformat
}}
</td>
</td>
{% endif %}
{% endif %}
{% endblock %}
{% endblock %}
...
...
flask_admin/templates/admin/model/list.html
View file @
4ec6473a
...
@@ -99,6 +99,7 @@
...
@@ -99,6 +99,7 @@
<input
type=
"checkbox"
name=
"rowid"
class=
"action-checkbox"
value=
"{{ get_pk_value(row) }}"
title=
"{{ _gettext('Select record') }}"
/>
<input
type=
"checkbox"
name=
"rowid"
class=
"action-checkbox"
value=
"{{ get_pk_value(row) }}"
title=
"{{ _gettext('Select record') }}"
/>
</td>
</td>
{% endif %}
{% endif %}
{% block list_row_actions_column scoped %}
<td>
<td>
{% block list_row_actions scoped %}
{% block list_row_actions scoped %}
{%- if admin_view.can_edit -%}
{%- if admin_view.can_edit -%}
...
@@ -118,6 +119,7 @@
...
@@ -118,6 +119,7 @@
{%- endif -%}
{%- endif -%}
{% endblock %}
{% endblock %}
</td>
</td>
{% endblock %}
{% for c, name in list_columns %}
{% for c, name in list_columns %}
<td>
{{ get_value(row, c) }}
</td>
<td>
{{ get_value(row, c) }}
</td>
{% endfor %}
{% endfor %}
...
...
flask_admin/tests/data/copyleft.gif
0 → 100644
View file @
4ec6473a
1.54 KB
flask_admin/tests/data/copyleft.jpeg
0 → 100644
View file @
4ec6473a
12.4 KB
flask_admin/tests/sqlamodel/test_basic.py
View file @
4ec6473a
...
@@ -833,3 +833,26 @@ def test_ajax_fk_multi():
...
@@ -833,3 +833,26 @@ def test_ajax_fk_multi():
ok_
(
mdl
is
not
None
)
ok_
(
mdl
is
not
None
)
ok_
(
mdl
.
model1
is
not
None
)
ok_
(
mdl
.
model1
is
not
None
)
eq_
(
len
(
mdl
.
model1
),
1
)
eq_
(
len
(
mdl
.
model1
),
1
)
def
test_safe_redirect
():
app
,
db
,
admin
=
setup
()
Model1
,
_
=
create_models
(
db
)
db
.
create_all
()
view
=
CustomModelView
(
Model1
,
db
.
session
)
admin
.
add_view
(
view
)
client
=
app
.
test_client
()
rv
=
client
.
post
(
'/admin/model1view/new/?url=http://localhost/admin/model2view/'
,
data
=
dict
(
test1
=
'test1large'
,
test2
=
'test2'
))
eq_
(
rv
.
status_code
,
302
)
eq_
(
rv
.
location
,
'http://localhost/admin/model2view/'
)
rv
=
client
.
post
(
'/admin/model1view/new/?url=http://google.com/evil/'
,
data
=
dict
(
test1
=
'test1large'
,
test2
=
'test2'
))
eq_
(
rv
.
status_code
,
302
)
eq_
(
rv
.
location
,
'http://localhost/admin/model1view/'
)
flask_admin/tests/test_form_upload.py
View file @
4ec6473a
...
@@ -95,6 +95,10 @@ def test_image_upload_field():
...
@@ -95,6 +95,10 @@ def test_image_upload_field():
safe_delete
(
path
,
'test2.png'
)
safe_delete
(
path
,
'test2.png'
)
safe_delete
(
path
,
'test2_thumb.jpg'
)
safe_delete
(
path
,
'test2_thumb.jpg'
)
safe_delete
(
path
,
'test1.jpg'
)
safe_delete
(
path
,
'test1.jpg'
)
safe_delete
(
path
,
'test1.jpeg'
)
safe_delete
(
path
,
'test1.gif'
)
safe_delete
(
path
,
'test1.png'
)
safe_delete
(
path
,
'test1.tiff'
)
class
TestForm
(
form
.
BaseForm
):
class
TestForm
(
form
.
BaseForm
):
upload
=
form
.
ImageUploadField
(
'Upload'
,
upload
=
form
.
ImageUploadField
(
'Upload'
,
...
@@ -204,6 +208,25 @@ def test_image_upload_field():
...
@@ -204,6 +208,25 @@ def test_image_upload_field():
ok_
(
op
.
exists
(
op
.
join
(
path
,
'test1.jpg'
)))
ok_
(
op
.
exists
(
op
.
join
(
path
,
'test1.jpg'
)))
# check allowed extensions
for
extension
in
(
'gif'
,
'jpg'
,
'jpeg'
,
'png'
,
'tiff'
):
filename
=
'copyleft.'
+
extension
filepath
=
op
.
join
(
op
.
dirname
(
__file__
),
'data'
,
filename
)
with
open
(
filepath
,
'rb'
)
as
fp
:
with
app
.
test_request_context
(
method
=
'POST'
,
data
=
{
'upload'
:
(
fp
,
filename
)}):
my_form
=
TestNoResizeForm
(
helpers
.
get_form_data
())
ok_
(
my_form
.
validate
())
my_form
.
populate_obj
(
dummy
)
eq_
(
dummy
.
upload
,
my_form
.
upload
.
data
.
filename
)
# check case-sensitivity for extensions
filename
=
op
.
join
(
op
.
dirname
(
__file__
),
'data'
,
'copyleft.jpg'
)
with
open
(
filename
,
'rb'
)
as
fp
:
with
app
.
test_request_context
(
method
=
'POST'
,
data
=
{
'upload'
:
(
fp
,
'copyleft.JPG'
)}):
my_form
=
TestNoResizeForm
(
helpers
.
get_form_data
())
ok_
(
my_form
.
validate
())
def
test_relative_path
():
def
test_relative_path
():
app
=
Flask
(
__name__
)
app
=
Flask
(
__name__
)
...
...
flask_admin/translations/ru/LC_MESSAGES/admin.po
View file @
4ec6473a
...
@@ -254,6 +254,10 @@ msgstr "Создать"
...
@@ -254,6 +254,10 @@ msgstr "Создать"
msgid "Save and Add"
msgid "Save and Add"
msgstr "Сохранить и Добавить"
msgstr "Сохранить и Добавить"
#: ../flask_admin/templates/admin/model/edit.html:6
msgid "Save and Continue"
msgstr "Сохранить и Продолжить"
#: ../flask_admin/templates/admin/model/inline_form_list.html:24
#: ../flask_admin/templates/admin/model/inline_form_list.html:24
msgid "Delete?"
msgid "Delete?"
msgstr "Удалить?"
msgstr "Удалить?"
...
...
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