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
2f280a80
Commit
2f280a80
authored
Jun 02, 2015
by
Petrus J.v.Rensburg
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into examples
parents
6f628968
ff878092
Changes
24
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
181 additions
and
56 deletions
+181
-56
view.py
flask_admin/contrib/appengine/view.py
+2
-2
filters.py
flask_admin/contrib/mongoengine/filters.py
+2
-2
form.py
flask_admin/contrib/mongoengine/form.py
+2
-2
view.py
flask_admin/contrib/mongoengine/view.py
+1
-1
filters.py
flask_admin/contrib/peewee/filters.py
+1
-1
view.py
flask_admin/contrib/peewee/view.py
+1
-1
view.py
flask_admin/contrib/pymongo/view.py
+1
-1
filters.py
flask_admin/contrib/sqla/filters.py
+1
-1
view.py
flask_admin/contrib/sqla/view.py
+1
-1
helpers.py
flask_admin/helpers.py
+4
-3
base.py
flask_admin/model/base.py
+11
-3
filters.py
flask_admin/model/filters.py
+1
-1
form-1.0.0.js
flask_admin/static/admin/js/form-1.0.0.js
+30
-0
loader.gif
flask_admin/static/vendor/leaflet/images/loader.gif
+0
-0
search-icon.png
flask_admin/static/vendor/leaflet/images/search-icon.png
+0
-0
leaflet.search.css
flask_admin/static/vendor/leaflet/leaflet.search.css
+18
-0
leaflet.search.js
flask_admin/static/vendor/leaflet/leaflet.search.js
+17
-0
lib.html
flask_admin/templates/bootstrap2/admin/lib.html
+8
-1
inline_field_list.html
...n/templates/bootstrap2/admin/model/inline_field_list.html
+8
-0
base.html
flask_admin/templates/bootstrap3/admin/base.html
+1
-1
inline_field_list.html
...n/templates/bootstrap3/admin/model/inline_field_list.html
+8
-0
test_basic.py
flask_admin/tests/mongoengine/test_basic.py
+28
-4
test_basic.py
flask_admin/tests/peeweemodel/test_basic.py
+4
-4
test_basic.py
flask_admin/tests/sqla/test_basic.py
+31
-27
No files found.
flask_admin/contrib/appengine/view.py
View file @
2f280a80
...
@@ -56,7 +56,7 @@ class NdbModelView(BaseModelView):
...
@@ -56,7 +56,7 @@ class NdbModelView(BaseModelView):
model
=
self
.
model
()
model
=
self
.
model
()
form
.
populate_obj
(
model
)
form
.
populate_obj
(
model
)
model
.
put
()
model
.
put
()
return
True
return
model
except
Exception
as
ex
:
except
Exception
as
ex
:
if
not
self
.
handle_view_exception
(
ex
):
if
not
self
.
handle_view_exception
(
ex
):
#flash(gettext('Failed to create record. %(error)s',
#flash(gettext('Failed to create record. %(error)s',
...
@@ -137,7 +137,7 @@ class DbModelView(BaseModelView):
...
@@ -137,7 +137,7 @@ class DbModelView(BaseModelView):
model
=
self
.
model
()
model
=
self
.
model
()
form
.
populate_obj
(
model
)
form
.
populate_obj
(
model
)
model
.
put
()
model
.
put
()
return
True
return
model
except
Exception
as
ex
:
except
Exception
as
ex
:
if
not
self
.
handle_view_exception
(
ex
):
if
not
self
.
handle_view_exception
(
ex
):
#flash(gettext('Failed to create record. %(error)s',
#flash(gettext('Failed to create record. %(error)s',
...
...
flask_admin/contrib/mongoengine/filters.py
View file @
2f280a80
...
@@ -221,9 +221,9 @@ class DateTimeNotBetweenFilter(DateTimeBetweenFilter):
...
@@ -221,9 +221,9 @@ class DateTimeNotBetweenFilter(DateTimeBetweenFilter):
return
lazy_gettext
(
'not between'
)
return
lazy_gettext
(
'not between'
)
# Base
peewe
e filter field converter
# Base
MongoEngin
e filter field converter
class
FilterConverter
(
filters
.
BaseFilterConverter
):
class
FilterConverter
(
filters
.
BaseFilterConverter
):
strings
=
(
Filter
Equal
,
FilterNotEqual
,
FilterLike
,
FilterNotLike
,
strings
=
(
Filter
Like
,
FilterNotLike
,
FilterEqual
,
FilterNotEqual
,
FilterEmpty
,
FilterInList
,
FilterNotInList
)
FilterEmpty
,
FilterInList
,
FilterNotInList
)
int_filters
=
(
IntEqualFilter
,
IntNotEqualFilter
,
IntGreaterFilter
,
int_filters
=
(
IntEqualFilter
,
IntNotEqualFilter
,
IntGreaterFilter
,
IntSmallerFilter
,
FilterEmpty
,
IntInListFilter
,
IntSmallerFilter
,
FilterEmpty
,
IntInListFilter
,
...
...
flask_admin/contrib/mongoengine/form.py
View file @
2f280a80
from
mongoengine
import
ReferenceField
from
mongoengine
import
ReferenceField
,
ListField
from
mongoengine.base
import
BaseDocument
,
DocumentMetaclass
,
get_document
from
mongoengine.base
import
BaseDocument
,
DocumentMetaclass
,
get_document
from
wtforms
import
fields
,
validators
from
wtforms
import
fields
,
validators
...
@@ -72,7 +72,7 @@ class CustomModelConverter(orm.ModelConverter):
...
@@ -72,7 +72,7 @@ class CustomModelConverter(orm.ModelConverter):
if
field
.
required
:
if
field
.
required
:
kwargs
[
'validators'
]
.
append
(
validators
.
Required
())
kwargs
[
'validators'
]
.
append
(
validators
.
Required
())
el
se
:
el
if
not
isinstance
(
field
,
ListField
)
:
kwargs
[
'validators'
]
.
append
(
validators
.
Optional
())
kwargs
[
'validators'
]
.
append
(
validators
.
Optional
())
ftype
=
type
(
field
)
.
__name__
ftype
=
type
(
field
)
.
__name__
...
...
flask_admin/contrib/mongoengine/view.py
View file @
2f280a80
...
@@ -544,7 +544,7 @@ class ModelView(BaseModelView):
...
@@ -544,7 +544,7 @@ class ModelView(BaseModelView):
else
:
else
:
self
.
after_model_change
(
form
,
model
,
True
)
self
.
after_model_change
(
form
,
model
,
True
)
return
True
return
model
def
update_model
(
self
,
form
,
model
):
def
update_model
(
self
,
form
,
model
):
"""
"""
...
...
flask_admin/contrib/peewee/filters.py
View file @
2f280a80
...
@@ -284,7 +284,7 @@ class TimeNotBetweenFilter(TimeBetweenFilter):
...
@@ -284,7 +284,7 @@ class TimeNotBetweenFilter(TimeBetweenFilter):
# Base peewee filter field converter
# Base peewee filter field converter
class
FilterConverter
(
filters
.
BaseFilterConverter
):
class
FilterConverter
(
filters
.
BaseFilterConverter
):
strings
=
(
Filter
Equal
,
FilterNotEqual
,
FilterLike
,
FilterNotLike
,
strings
=
(
Filter
Like
,
FilterNotLike
,
FilterEqual
,
FilterNotEqual
,
FilterEmpty
,
FilterInList
,
FilterNotInList
)
FilterEmpty
,
FilterInList
,
FilterNotInList
)
int_filters
=
(
IntEqualFilter
,
IntNotEqualFilter
,
IntGreaterFilter
,
int_filters
=
(
IntEqualFilter
,
IntNotEqualFilter
,
IntGreaterFilter
,
IntSmallerFilter
,
FilterEmpty
,
IntInListFilter
,
IntSmallerFilter
,
FilterEmpty
,
IntInListFilter
,
...
...
flask_admin/contrib/peewee/view.py
View file @
2f280a80
...
@@ -384,7 +384,7 @@ class ModelView(BaseModelView):
...
@@ -384,7 +384,7 @@ class ModelView(BaseModelView):
else
:
else
:
self
.
after_model_change
(
form
,
model
,
True
)
self
.
after_model_change
(
form
,
model
,
True
)
return
True
return
model
def
update_model
(
self
,
form
,
model
):
def
update_model
(
self
,
form
,
model
):
try
:
try
:
...
...
flask_admin/contrib/pymongo/view.py
View file @
2f280a80
...
@@ -288,7 +288,7 @@ class ModelView(BaseModelView):
...
@@ -288,7 +288,7 @@ class ModelView(BaseModelView):
else
:
else
:
self
.
after_model_change
(
form
,
model
,
True
)
self
.
after_model_change
(
form
,
model
,
True
)
return
True
return
model
def
update_model
(
self
,
form
,
model
):
def
update_model
(
self
,
form
,
model
):
"""
"""
...
...
flask_admin/contrib/sqla/filters.py
View file @
2f280a80
...
@@ -285,7 +285,7 @@ class TimeNotBetweenFilter(TimeBetweenFilter):
...
@@ -285,7 +285,7 @@ class TimeNotBetweenFilter(TimeBetweenFilter):
# Base SQLA filter field converter
# Base SQLA filter field converter
class
FilterConverter
(
filters
.
BaseFilterConverter
):
class
FilterConverter
(
filters
.
BaseFilterConverter
):
strings
=
(
Filter
Equal
,
FilterNotEqual
,
FilterLike
,
FilterNotLike
,
strings
=
(
Filter
Like
,
FilterNotLike
,
FilterEqual
,
FilterNotEqual
,
FilterEmpty
,
FilterInList
,
FilterNotInList
)
FilterEmpty
,
FilterInList
,
FilterNotInList
)
int_filters
=
(
IntEqualFilter
,
IntNotEqualFilter
,
IntGreaterFilter
,
int_filters
=
(
IntEqualFilter
,
IntNotEqualFilter
,
IntGreaterFilter
,
IntSmallerFilter
,
FilterEmpty
,
IntInListFilter
,
IntSmallerFilter
,
FilterEmpty
,
IntInListFilter
,
...
...
flask_admin/contrib/sqla/view.py
View file @
2f280a80
...
@@ -894,7 +894,7 @@ class ModelView(BaseModelView):
...
@@ -894,7 +894,7 @@ class ModelView(BaseModelView):
else
:
else
:
self
.
after_model_change
(
form
,
model
,
True
)
self
.
after_model_change
(
form
,
model
,
True
)
return
True
return
model
def
update_model
(
self
,
form
,
model
):
def
update_model
(
self
,
form
,
model
):
"""
"""
...
...
flask_admin/helpers.py
View file @
2f280a80
...
@@ -87,9 +87,10 @@ def is_field_error(errors):
...
@@ -87,9 +87,10 @@ def is_field_error(errors):
:param errors:
:param errors:
Errors list.
Errors list.
"""
"""
for
e
in
errors
:
if
isinstance
(
errors
,
(
list
,
tuple
)):
if
isinstance
(
e
,
string_types
):
for
e
in
errors
:
return
True
if
isinstance
(
e
,
string_types
):
return
True
return
False
return
False
...
...
flask_admin/model/base.py
View file @
2f280a80
...
@@ -1243,7 +1243,7 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -1243,7 +1243,7 @@ class BaseModelView(BaseView, ActionsMixin):
"""
"""
Create model from the form.
Create model from the form.
Returns
`True`
if operation succeeded.
Returns
the model instance
if operation succeeded.
Must be implemented in the child class.
Must be implemented in the child class.
...
@@ -1550,12 +1550,20 @@ class BaseModelView(BaseView, ActionsMixin):
...
@@ -1550,12 +1550,20 @@ class BaseModelView(BaseView, ActionsMixin):
self
.
_validate_form_instance
(
ruleset
=
self
.
_form_create_rules
,
form
=
form
)
self
.
_validate_form_instance
(
ruleset
=
self
.
_form_create_rules
,
form
=
form
)
if
self
.
validate_form
(
form
):
if
self
.
validate_form
(
form
):
if
self
.
create_model
(
form
):
# in versions 1.1.0 and before, this returns a boolean
# in later versions, this is the model itself
model
=
self
.
create_model
(
form
)
if
model
:
flash
(
gettext
(
'Record was successfully created.'
))
flash
(
gettext
(
'Record was successfully created.'
))
if
'_add_another'
in
request
.
form
:
if
'_add_another'
in
request
.
form
:
return
redirect
(
request
.
url
)
return
redirect
(
request
.
url
)
else
:
else
:
return
redirect
(
return_url
)
# if we have a valid model, try to go to the edit view
if
model
is
not
True
:
url
=
self
.
get_url
(
'.edit_view'
,
id
=
self
.
get_pk_value
(
model
),
url
=
return_url
)
else
:
url
=
return_url
return
redirect
(
url
)
form_opts
=
FormOpts
(
widget_args
=
self
.
form_widget_args
,
form_opts
=
FormOpts
(
widget_args
=
self
.
form_widget_args
,
form_rules
=
self
.
_form_create_rules
)
form_rules
=
self
.
_form_create_rules
)
...
...
flask_admin/model/filters.py
View file @
2f280a80
...
@@ -266,7 +266,7 @@ def convert(*args):
...
@@ -266,7 +266,7 @@ def convert(*args):
See :mod:`flask_admin.contrib.sqla.filters` for usage example.
See :mod:`flask_admin.contrib.sqla.filters` for usage example.
"""
"""
def
_inner
(
func
):
def
_inner
(
func
):
func
.
_converter_for
=
list
(
map
(
str
.
lower
,
args
))
func
.
_converter_for
=
list
(
map
(
lambda
x
:
x
.
lower
()
,
args
))
return
func
return
func
return
_inner
return
_inner
...
...
flask_admin/static/admin/js/form-1.0.0.js
View file @
2f280a80
...
@@ -194,6 +194,36 @@
...
@@ -194,6 +194,36 @@
var
drawControl
=
new
L
.
Control
.
Draw
(
drawOptions
);
var
drawControl
=
new
L
.
Control
.
Draw
(
drawOptions
);
map
.
addControl
(
drawControl
);
map
.
addControl
(
drawControl
);
if
(
window
.
google
)
{
var
geocoder
=
new
google
.
maps
.
Geocoder
();
function
googleGeocoding
(
text
,
callResponse
)
{
geocoder
.
geocode
({
address
:
text
},
callResponse
);
}
function
filterJSONCall
(
rawjson
)
{
var
json
=
{},
key
,
loc
,
disp
=
[];
for
(
var
i
in
rawjson
)
{
key
=
rawjson
[
i
].
formatted_address
;
loc
=
L
.
latLng
(
rawjson
[
i
].
geometry
.
location
.
lat
(),
rawjson
[
i
].
geometry
.
location
.
lng
());
json
[
key
]
=
loc
;
}
return
json
;
}
map
.
addControl
(
new
L
.
Control
.
Search
({
callData
:
googleGeocoding
,
filterJSON
:
filterJSONCall
,
markerLocation
:
true
,
autoType
:
false
,
autoCollapse
:
true
,
minLength
:
2
,
zoom
:
10
}));
}
// save when the editableLayers are edited
// save when the editableLayers are edited
var
saveToTextArea
=
function
()
{
var
saveToTextArea
=
function
()
{
var
geo
=
editableLayers
.
toGeoJSON
();
var
geo
=
editableLayers
.
toGeoJSON
();
...
...
flask_admin/static/vendor/leaflet/images/loader.gif
0 → 100644
View file @
2f280a80
1.81 KB
flask_admin/static/vendor/leaflet/images/search-icon.png
0 → 100644
View file @
2f280a80
3.75 KB
flask_admin/static/vendor/leaflet/leaflet.search.css
0 → 100644
View file @
2f280a80
/*
* Leaflet Control Search v1.5.7 - 2015-05-07
*
* Copyright 2014 Stefano Cudini
* stefano.cudini@gmail.com
* http://labs.easyblog.it/
*
* Licensed under the MIT license.
*
* Demo:
* http://labs.easyblog.it/maps/leaflet-search/
*
* Source:
* git@github.com:stefanocudini/leaflet-search.git
*
*/
.leaflet-container
.leaflet-control-search
{
position
:
relative
;
float
:
left
;
background
:
#fff
;
color
:
#1978cf
;
-moz-border-radius
:
4px
;
-webkit-border-radius
:
4px
;
border-radius
:
4px
;
background-color
:
rgba
(
255
,
255
,
255
,
.8
);
z-index
:
1000
;
box-shadow
:
0
1px
7px
rgba
(
0
,
0
,
0
,
.65
);
margin-left
:
10px
;
margin-top
:
10px
}
.leaflet-control-search.search-exp
{
box-shadow
:
0
1px
7px
#999
;
background
:
#fff
}
.leaflet-control-search
.search-input
{
display
:
block
;
float
:
left
;
background
:
#fff
;
border
:
1px
solid
#666
;
border-radius
:
2px
;
height
:
18px
;
padding
:
0
18px
0
2px
;
margin
:
3px
0
3px
3px
}
.leaflet-control-search.search-load
.search-input
{
background
:
url(./images/loader.gif)
no-repeat
center
right
#fff
}
.leaflet-control-search.search-load
.search-cancel
{
visibility
:
hidden
}
.leaflet-control-search
.search-cancel
{
display
:
block
;
width
:
22px
;
height
:
18px
;
position
:
absolute
;
right
:
22px
;
margin
:
3px
0
;
background
:
url(./images/search-icon.png)
no-repeat
0
-46px
;
text-decoration
:
none
;
filter
:
alpha
(
opacity
=
80
);
opacity
:
.8
}
.leaflet-control-search
.search-cancel
:hover
{
filter
:
alpha
(
opacity
=
100
);
opacity
:
1
}
.leaflet-control-search
.search-cancel
span
{
display
:
none
;
font-size
:
18px
;
line-height
:
20px
;
color
:
#ccc
;
font-weight
:
700
}
.leaflet-control-search
.search-cancel
:hover
span
{
color
:
#aaa
}
.leaflet-control-search
.search-button
{
display
:
block
;
float
:
left
;
width
:
26px
;
height
:
26px
;
background
:
url(./images/search-icon.png)
no-repeat
2px
2px
;
border-radius
:
4px
}
.leaflet-control-search
.search-button
:hover
{
background
:
url(./images/search-icon.png)
no-repeat
2px
-22px
}
.leaflet-control-search
.search-tooltip
{
position
:
absolute
;
top
:
100%
;
left
:
0
;
float
:
left
;
min-width
:
120px
;
max-height
:
122px
;
box-shadow
:
1px
1px
6px
rgba
(
0
,
0
,
0
,
.4
);
background-color
:
rgba
(
0
,
0
,
0
,
.25
);
z-index
:
1010
;
overflow-y
:
auto
;
overflow-x
:
hidden
}
.leaflet-control-search
.search-tip
{
margin
:
2px
;
padding
:
2px
4px
;
display
:
block
;
color
:
#000
;
background
:
#eee
;
border-radius
:
.25em
;
text-decoration
:
none
;
white-space
:
nowrap
;
vertical-align
:
center
}
.leaflet-control-search
.search-button
:hover
,
.leaflet-control-search
.search-tip-select
,
.leaflet-control-search
.search-tip
:hover
{
background-color
:
#fff
}
.leaflet-control-search
.search-alert
{
cursor
:
pointer
;
clear
:
both
;
font-size
:
.75em
;
margin-bottom
:
5px
;
padding
:
0
.25em
;
color
:
#e00
;
font-weight
:
700
;
border-radius
:
.25em
}
flask_admin/static/vendor/leaflet/leaflet.search.js
0 → 100644
View file @
2f280a80
This diff is collapsed.
Click to expand it.
flask_admin/templates/bootstrap2/admin/lib.html
View file @
2f280a80
...
@@ -97,7 +97,7 @@
...
@@ -97,7 +97,7 @@
<p
class=
"help-block"
>
{{ field.description }}
</p>
<p
class=
"help-block"
>
{{ field.description }}
</p>
{% endif %}
{% endif %}
{% if direct_error %}
{% if direct_error %}
<ul
{%
if
direct_error
%}
class=
"input-errors"
{%
endif
%}
>
<ul
class=
"input-errors"
>
{% for e in field.errors if e is string %}
{% for e in field.errors if e is string %}
<li>
{{ e }}
</li>
<li>
{{ e }}
</li>
{% endfor %}
{% endfor %}
...
@@ -177,6 +177,9 @@
...
@@ -177,6 +177,9 @@
{% if config.MAPBOX_MAP_ID %}
{% if config.MAPBOX_MAP_ID %}
<link
href=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.css') }}"
rel=
"stylesheet"
>
<link
href=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.css') }}"
rel=
"stylesheet"
>
<link
href=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.draw.css') }}"
rel=
"stylesheet"
>
<link
href=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.draw.css') }}"
rel=
"stylesheet"
>
{% if config.MAPBOX_SEARCH %}
<link
href=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.search.css') }}"
rel=
"stylesheet"
>
{% endif %}
{% endif %}
{% endif %}
{% if editable_columns %}
{% if editable_columns %}
<link
href=
"{{ admin_static.url(filename='vendor/x-editable/css/bootstrap2-editable-1.5.1.css') }}"
rel=
"stylesheet"
>
<link
href=
"{{ admin_static.url(filename='vendor/x-editable/css/bootstrap2-editable-1.5.1.css') }}"
rel=
"stylesheet"
>
...
@@ -193,6 +196,10 @@
...
@@ -193,6 +196,10 @@
</script>
</script>
<script
src=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.js') }}"
></script>
<script
src=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.js') }}"
></script>
<script
src=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.draw.js') }}"
></script>
<script
src=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.draw.js') }}"
></script>
{% if config.MAPBOX_SEARCH %}
<script
src=
"https://maps.googleapis.com/maps/api/js?v=3&sensor=false"
></script>
<script
src=
"{{ admin_static.url(filename='vendor/leaflet/leaflet.search.js') }}"
></script>
{% endif %}
{% endif %}
{% endif %}
<script
src=
"{{ admin_static.url(filename='vendor/bootstrap-daterangepicker/daterangepicker.js') }}"
></script>
<script
src=
"{{ admin_static.url(filename='vendor/bootstrap-daterangepicker/daterangepicker.js') }}"
></script>
{% if editable_columns %}
{% if editable_columns %}
...
...
flask_admin/templates/bootstrap2/admin/model/inline_field_list.html
View file @
2f280a80
...
@@ -2,6 +2,14 @@
...
@@ -2,6 +2,14 @@
{% macro render_field(field) %}
{% macro render_field(field) %}
{{ field }}
{{ field }}
{% if h.is_field_error(field.errors) %}
<ul
class=
"input-errors"
>
{% for e in field.errors if e is string %}
<li>
{{ e }}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
{% endmacro %}
{{ base.render_inline_fields(field, template, render_field, check) }}
{{ base.render_inline_fields(field, template, render_field, check) }}
flask_admin/templates/bootstrap3/admin/base.html
View file @
2f280a80
...
@@ -51,7 +51,7 @@
...
@@ -51,7 +51,7 @@
{% endblock %}
{% endblock %}
{% block menu_links %}
{% block menu_links %}
<ul
class=
"nav navbar-right"
>
<ul
class=
"nav navbar-
nav navbar-
right"
>
{{ layout.menu_links() }}
{{ layout.menu_links() }}
</ul>
</ul>
{% endblock %}
{% endblock %}
...
...
flask_admin/templates/bootstrap3/admin/model/inline_field_list.html
View file @
2f280a80
...
@@ -2,6 +2,14 @@
...
@@ -2,6 +2,14 @@
{% macro render_field(field) %}
{% macro render_field(field) %}
{{ field }}
{{ field }}
{% if h.is_field_error(field.errors) %}
<ul
class=
"help-block input-errors"
>
{% for e in field.errors if e is string %}
<li>
{{ e }}
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
{% endmacro %}
{{ base.render_inline_fields(field, template, render_field, check) }}
{{ base.render_inline_fields(field, template, render_field, check) }}
flask_admin/tests/mongoengine/test_basic.py
View file @
2f280a80
...
@@ -229,10 +229,10 @@ def test_column_filters():
...
@@ -229,10 +229,10 @@ def test_column_filters():
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Test1'
]],
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Test1'
]],
[
[
(
0
,
'
equal
s'
),
(
0
,
'
contain
s'
),
(
1
,
'not
equal
'
),
(
1
,
'not
contains
'
),
(
2
,
'
contain
s'
),
(
2
,
'
equal
s'
),
(
3
,
'not
contains
'
),
(
3
,
'not
equal
'
),
(
4
,
'empty'
),
(
4
,
'empty'
),
(
5
,
'in list'
),
(
5
,
'in list'
),
(
6
,
'not in list'
),
(
6
,
'not in list'
),
...
@@ -791,6 +791,30 @@ def test_nested_list_subdocument():
...
@@ -791,6 +791,30 @@ def test_nested_list_subdocument():
ok_
(
'value'
not
in
dir
(
inline_form
))
ok_
(
'value'
not
in
dir
(
inline_form
))
def
test_list_subdocument_validation
():
app
,
db
,
admin
=
setup
()
class
Comment
(
db
.
EmbeddedDocument
):
name
=
db
.
StringField
(
max_length
=
20
,
required
=
True
)
value
=
db
.
StringField
(
max_length
=
20
)
class
Model1
(
db
.
Document
):
test1
=
db
.
StringField
(
max_length
=
20
)
subdoc
=
db
.
ListField
(
db
.
EmbeddedDocumentField
(
Comment
))
view
=
CustomModelView
(
Model1
)
admin
.
add_view
(
view
)
client
=
app
.
test_client
()
rv
=
client
.
post
(
'/admin/model1/new/'
,
data
=
{
'test1'
:
'test1large'
,
'subdoc-0-name'
:
'comment'
,
'subdoc-0-value'
:
'test'
})
eq_
(
rv
.
status_code
,
302
)
rv
=
client
.
post
(
'/admin/model1/new/'
,
data
=
{
'test1'
:
'test1large'
,
'subdoc-0-name'
:
''
,
'subdoc-0-value'
:
'test'
})
eq_
(
rv
.
status_code
,
200
)
ok_
(
'This field is required'
in
rv
.
data
)
def
test_ajax_fk
():
def
test_ajax_fk
():
app
,
db
,
admin
=
setup
()
app
,
db
,
admin
=
setup
()
...
...
flask_admin/tests/peeweemodel/test_basic.py
View file @
2f280a80
...
@@ -263,10 +263,10 @@ def test_column_filters():
...
@@ -263,10 +263,10 @@ def test_column_filters():
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Test1'
]],
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Test1'
]],
[
[
(
0
,
'
equal
s'
),
(
0
,
'
contain
s'
),
(
1
,
'not
equal
'
),
(
1
,
'not
contains
'
),
(
2
,
'
contain
s'
),
(
2
,
'
equal
s'
),
(
3
,
'not
contains
'
),
(
3
,
'not
equal
'
),
(
4
,
'empty'
),
(
4
,
'empty'
),
(
5
,
'in list'
),
(
5
,
'in list'
),
(
6
,
'not in list'
),
(
6
,
'not in list'
),
...
...
flask_admin/tests/sqla/test_basic.py
View file @
2f280a80
from
nose.tools
import
eq_
,
ok_
,
raises
from
nose.tools
import
eq_
,
ok_
,
raises
,
assert_true
from
wtforms
import
fields
from
wtforms
import
fields
...
@@ -421,10 +421,10 @@ def test_column_filters():
...
@@ -421,10 +421,10 @@ def test_column_filters():
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Test1'
]],
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Test1'
]],
[
[
(
0
,
u'
equal
s'
),
(
0
,
u'
contain
s'
),
(
1
,
u'not
equal
'
),
(
1
,
u'not
contains
'
),
(
2
,
u'
contain
s'
),
(
2
,
u'
equal
s'
),
(
3
,
u'not
contains
'
),
(
3
,
u'not
equal
'
),
(
4
,
u'empty'
),
(
4
,
u'empty'
),
(
5
,
u'in list'
),
(
5
,
u'in list'
),
(
6
,
u'not in list'
),
(
6
,
u'not in list'
),
...
@@ -436,10 +436,10 @@ def test_column_filters():
...
@@ -436,10 +436,10 @@ def test_column_filters():
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Model1 / Test1'
]],
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Model1 / Test1'
]],
[
[
(
0
,
u'
equal
s'
),
(
0
,
u'
contain
s'
),
(
1
,
u'not
equal
'
),
(
1
,
u'not
contains
'
),
(
2
,
u'
contain
s'
),
(
2
,
u'
equal
s'
),
(
3
,
u'not
contains
'
),
(
3
,
u'not
equal
'
),
(
4
,
u'empty'
),
(
4
,
u'empty'
),
(
5
,
u'in list'
),
(
5
,
u'in list'
),
(
6
,
u'not in list'
),
(
6
,
u'not in list'
),
...
@@ -447,10 +447,10 @@ def test_column_filters():
...
@@ -447,10 +447,10 @@ def test_column_filters():
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Model1 / Test2'
]],
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Model1 / Test2'
]],
[
[
(
7
,
u'
equal
s'
),
(
7
,
u'
contain
s'
),
(
8
,
u'not
equal
'
),
(
8
,
u'not
contains
'
),
(
9
,
u'
contain
s'
),
(
9
,
u'
equal
s'
),
(
10
,
u'not
contains
'
),
(
10
,
u'not
equal
'
),
(
11
,
u'empty'
),
(
11
,
u'empty'
),
(
12
,
u'in list'
),
(
12
,
u'in list'
),
(
13
,
u'not in list'
),
(
13
,
u'not in list'
),
...
@@ -458,10 +458,10 @@ def test_column_filters():
...
@@ -458,10 +458,10 @@ def test_column_filters():
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Model1 / Test3'
]],
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Model1 / Test3'
]],
[
[
(
14
,
u'
equal
s'
),
(
14
,
u'
contain
s'
),
(
15
,
u'not
equal
'
),
(
15
,
u'not
contains
'
),
(
16
,
u'
contain
s'
),
(
16
,
u'
equal
s'
),
(
17
,
u'not
contains
'
),
(
17
,
u'not
equal
'
),
(
18
,
u'empty'
),
(
18
,
u'empty'
),
(
19
,
u'in list'
),
(
19
,
u'in list'
),
(
20
,
u'not in list'
),
(
20
,
u'not in list'
),
...
@@ -469,10 +469,10 @@ def test_column_filters():
...
@@ -469,10 +469,10 @@ def test_column_filters():
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Model1 / Test4'
]],
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Model1 / Test4'
]],
[
[
(
21
,
u'
equal
s'
),
(
21
,
u'
contain
s'
),
(
22
,
u'not
equal
'
),
(
22
,
u'not
contains
'
),
(
23
,
u'
contain
s'
),
(
23
,
u'
equal
s'
),
(
24
,
u'not
contains
'
),
(
24
,
u'not
equal
'
),
(
25
,
u'empty'
),
(
25
,
u'empty'
),
(
26
,
u'in list'
),
(
26
,
u'in list'
),
(
27
,
u'not in list'
),
(
27
,
u'not in list'
),
...
@@ -538,10 +538,10 @@ def test_column_filters():
...
@@ -538,10 +538,10 @@ def test_column_filters():
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Test1'
]],
eq_
([(
f
[
'index'
],
f
[
'operation'
])
for
f
in
view
.
_filter_groups
[
u'Test1'
]],
[
[
(
0
,
'
equal
s'
),
(
0
,
'
contain
s'
),
(
1
,
'not
equal
'
),
(
1
,
'not
contains
'
),
(
2
,
'
contain
s'
),
(
2
,
'
equal
s'
),
(
3
,
'not
contains
'
),
(
3
,
'not
equal
'
),
(
4
,
'empty'
),
(
4
,
'empty'
),
(
5
,
'in list'
),
(
5
,
'in list'
),
(
6
,
'not in list'
),
(
6
,
'not in list'
),
...
@@ -1669,10 +1669,14 @@ def test_safe_redirect():
...
@@ -1669,10 +1669,14 @@ def test_safe_redirect():
data
=
dict
(
test1
=
'test1large'
,
test2
=
'test2'
))
data
=
dict
(
test1
=
'test1large'
,
test2
=
'test2'
))
eq_
(
rv
.
status_code
,
302
)
eq_
(
rv
.
status_code
,
302
)
eq_
(
rv
.
location
,
'http://localhost/admin/model2view/'
)
assert_true
(
rv
.
location
.
startswith
(
'http://localhost/admin/model1/edit/'
))
assert_true
(
'url=http
%3
A
%2
F
%2
Flocalhost
%2
Fadmin
%2
Fmodel2view
%2
F'
in
rv
.
location
)
assert_true
(
'id=1'
in
rv
.
location
)
rv
=
client
.
post
(
'/admin/model1/new/?url=http://google.com/evil/'
,
rv
=
client
.
post
(
'/admin/model1/new/?url=http://google.com/evil/'
,
data
=
dict
(
test1
=
'test1large'
,
test2
=
'test2'
))
data
=
dict
(
test1
=
'test1large'
,
test2
=
'test2'
))
eq_
(
rv
.
status_code
,
302
)
eq_
(
rv
.
status_code
,
302
)
eq_
(
rv
.
location
,
'http://localhost/admin/model1/'
)
assert_true
(
rv
.
location
.
startswith
(
'http://localhost/admin/model1/edit/'
))
assert_true
(
'url=
%2
Fadmin
%2
Fmodel1
%2
F'
in
rv
.
location
)
assert_true
(
'id=2'
in
rv
.
location
)
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