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
efcc49ed
Commit
efcc49ed
authored
Aug 26, 2013
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Widget fixes, MongoEngine backend support
parent
8151015e
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
176 additions
and
15 deletions
+176
-15
ajax.py
flask_admin/contrib/mongoengine/ajax.py
+6
-1
fields.py
flask_admin/model/fields.py
+8
-5
widgets.py
flask_admin/model/widgets.py
+14
-3
form.js
flask_admin/static/admin/js/form.js
+2
-1
test_basic.py
flask_admin/tests/mongoengine/test_basic.py
+76
-1
test_basic.py
flask_admin/tests/sqlamodel/test_basic.py
+70
-4
No files found.
flask_admin/contrib/mongoengine/ajax.py
View file @
efcc49ed
...
@@ -39,4 +39,9 @@ class QueryAjaxModelLoader(AjaxModelLoader):
...
@@ -39,4 +39,9 @@ class QueryAjaxModelLoader(AjaxModelLoader):
else
:
else
:
criteria
|=
mongoengine
.
Q
(
**
flt
)
criteria
|=
mongoengine
.
Q
(
**
flt
)
return
query
.
filter
(
criteria
)
.
skip
(
offset
)
.
limit
(
limit
)
query
=
query
.
filter
(
criteria
)
if
offset
:
query
=
query
.
skip
(
offset
)
return
query
.
limit
(
limit
)
.
all
()
flask_admin/model/fields.py
View file @
efcc49ed
...
@@ -122,6 +122,8 @@ class AjaxSelectField(SelectFieldBase):
...
@@ -122,6 +122,8 @@ class AjaxSelectField(SelectFieldBase):
"""
"""
widget
=
AjaxSelect2Widget
()
widget
=
AjaxSelect2Widget
()
separator
=
','
def
__init__
(
self
,
loader
,
label
=
None
,
validators
=
None
,
allow_blank
=
False
,
blank_text
=
u''
,
**
kwargs
):
def
__init__
(
self
,
loader
,
label
=
None
,
validators
=
None
,
allow_blank
=
False
,
blank_text
=
u''
,
**
kwargs
):
super
(
AjaxSelectField
,
self
)
.
__init__
(
label
,
validators
,
**
kwargs
)
super
(
AjaxSelectField
,
self
)
.
__init__
(
label
,
validators
,
**
kwargs
)
self
.
loader
=
loader
self
.
loader
=
loader
...
@@ -170,6 +172,7 @@ class AjaxSelectMultipleField(AjaxSelectField):
...
@@ -170,6 +172,7 @@ class AjaxSelectMultipleField(AjaxSelectField):
def
__init__
(
self
,
loader
,
label
=
None
,
validators
=
None
,
default
=
None
,
**
kwargs
):
def
__init__
(
self
,
loader
,
label
=
None
,
validators
=
None
,
default
=
None
,
**
kwargs
):
if
default
is
None
:
if
default
is
None
:
default
=
[]
default
=
[]
super
(
AjaxSelectMultipleField
,
self
)
.
__init__
(
loader
,
label
,
validators
,
default
=
default
,
**
kwargs
)
super
(
AjaxSelectMultipleField
,
self
)
.
__init__
(
loader
,
label
,
validators
,
default
=
default
,
**
kwargs
)
self
.
_invalid_formdata
=
False
self
.
_invalid_formdata
=
False
...
@@ -198,12 +201,12 @@ class AjaxSelectMultipleField(AjaxSelectField):
...
@@ -198,12 +201,12 @@ class AjaxSelectMultipleField(AjaxSelectField):
data
=
property
(
_get_data
,
_set_data
)
data
=
property
(
_get_data
,
_set_data
)
def
process_formdata
(
self
,
valuelist
):
def
process_formdata
(
self
,
valuelist
):
self
.
_formdata
=
set
(
valuelist
)
self
.
_formdata
=
set
()
for
field
in
valuelist
:
for
n
in
field
.
split
(
self
.
separator
):
self
.
_formdata
.
add
(
n
)
def
pre_validate
(
self
,
form
):
def
pre_validate
(
self
,
form
):
if
self
.
_invalid_formdata
:
if
self
.
_invalid_formdata
:
raise
ValidationError
(
self
.
gettext
(
u'Not a valid choice'
))
raise
ValidationError
(
self
.
gettext
(
u'Not a valid choice'
))
elif
self
.
data
:
for
item
in
self
.
data
:
if
not
self
.
loader
.
get_one
(
item
):
raise
ValidationError
(
self
.
gettext
(
u'Not a valid choice'
))
flask_admin/model/widgets.py
View file @
efcc49ed
from
flask
import
url_for
,
json
from
flask
import
url_for
,
json
from
wtforms.widgets
import
HTMLString
,
html_params
from
wtforms.widgets
import
HTMLString
,
html_params
from
flask.ext.admin._compat
import
as_unicode
from
flask.ext.admin.form
import
RenderTemplateWidget
from
flask.ext.admin.form
import
RenderTemplateWidget
...
@@ -31,13 +32,23 @@ class AjaxSelect2Widget(object):
...
@@ -31,13 +32,23 @@ class AjaxSelect2Widget(object):
if
self
.
multiple
:
if
self
.
multiple
:
result
=
[]
result
=
[]
ids
=
[]
for
value
in
field
.
data
:
for
value
in
field
.
data
:
result
.
append
(
field
.
loader
.
format
(
value
))
data
=
field
.
loader
.
format
(
value
)
result
.
append
(
data
)
ids
.
append
(
as_unicode
(
data
[
0
]))
kwargs
[
'value'
]
=
json
.
dumps
(
result
)
separator
=
getattr
(
field
,
'separator'
,
','
)
kwargs
[
'value'
]
=
separator
.
join
(
ids
)
kwargs
[
'data-json'
]
=
json
.
dumps
(
result
)
kwargs
[
'data-multiple'
]
=
u'1'
kwargs
[
'data-multiple'
]
=
u'1'
else
:
else
:
kwargs
[
'value'
]
=
json
.
dumps
(
field
.
loader
.
format
(
field
.
data
))
data
=
field
.
loader
.
format
(
field
.
data
)
if
data
:
kwargs
[
'value'
]
=
data
[
0
]
kwargs
[
'data-json'
]
=
json
.
dumps
(
data
)
return
HTMLString
(
'<input
%
s>'
%
html_params
(
name
=
field
.
name
,
**
kwargs
))
return
HTMLString
(
'<input
%
s>'
%
html_params
(
name
=
field
.
name
,
**
kwargs
))
flask_admin/static/admin/js/form.js
View file @
efcc49ed
...
@@ -37,7 +37,8 @@
...
@@ -37,7 +37,8 @@
}
}
},
},
initSelection
:
function
(
element
,
callback
)
{
initSelection
:
function
(
element
,
callback
)
{
var
value
=
jQuery
.
parseJSON
(
element
.
val
());
$el
=
$
(
element
);
var
value
=
jQuery
.
parseJSON
(
$el
.
attr
(
'data-json'
));
var
result
=
null
;
var
result
=
null
;
if
(
value
)
{
if
(
value
)
{
...
...
flask_admin/tests/mongoengine/test_basic.py
View file @
efcc49ed
...
@@ -2,7 +2,7 @@ from nose.tools import eq_, ok_
...
@@ -2,7 +2,7 @@ from nose.tools import eq_, ok_
from
nose.plugins.skip
import
SkipTest
from
nose.plugins.skip
import
SkipTest
# Skip test on PY3
# Skip test on PY3
from
flask.ext.admin._compat
import
PY2
from
flask.ext.admin._compat
import
PY2
,
as_unicode
if
not
PY2
:
if
not
PY2
:
raise
SkipTest
(
'MongoEngine is not Python 3 compatible'
)
raise
SkipTest
(
'MongoEngine is not Python 3 compatible'
)
...
@@ -350,3 +350,78 @@ def test_nested_list_subdocument():
...
@@ -350,3 +350,78 @@ def test_nested_list_subdocument():
ok_
(
'name'
in
dir
(
inline_form
))
ok_
(
'name'
in
dir
(
inline_form
))
ok_
(
'value'
not
in
dir
(
inline_form
))
ok_
(
'value'
not
in
dir
(
inline_form
))
def
test_ajax_fk
():
app
,
db
,
admin
=
setup
()
class
Model1
(
db
.
Document
):
test1
=
db
.
StringField
(
max_length
=
20
)
test2
=
db
.
StringField
(
max_length
=
20
)
def
__str__
(
self
):
return
self
.
test1
class
Model2
(
db
.
Document
):
int_field
=
db
.
IntField
()
bool_field
=
db
.
BooleanField
()
model1
=
db
.
ReferenceField
(
Model1
)
Model1
.
objects
.
delete
()
Model2
.
objects
.
delete
()
view
=
CustomModelView
(
Model2
,
url
=
'view'
,
form_ajax_refs
=
{
'model1'
:
(
'test1'
,
'test2'
)
}
)
admin
.
add_view
(
view
)
ok_
(
u'model1'
in
view
.
_form_ajax_refs
)
model
=
Model1
(
test1
=
u'first'
)
model
.
save
()
model2
=
Model1
(
test1
=
u'foo'
,
test2
=
u'bar'
)
.
save
()
# Check loader
loader
=
view
.
_form_ajax_refs
[
u'model1'
]
mdl
=
loader
.
get_one
(
model
.
id
)
eq_
(
mdl
.
test1
,
model
.
test1
)
items
=
loader
.
get_list
(
u'fir'
)
eq_
(
len
(
items
),
1
)
eq_
(
items
[
0
]
.
id
,
model
.
id
)
items
=
loader
.
get_list
(
u'bar'
)
eq_
(
len
(
items
),
1
)
eq_
(
items
[
0
]
.
test1
,
u'foo'
)
# Check form generation
form
=
view
.
create_form
()
eq_
(
form
.
model1
.
__class__
.
__name__
,
u'AjaxSelectField'
)
with
app
.
test_request_context
(
'/admin/view/'
):
ok_
(
u'value=""'
not
in
form
.
model1
())
form
.
model1
.
data
=
model
needle
=
u'data-json="["
%
s", "first"]"'
%
as_unicode
(
model
.
id
)
ok_
(
needle
in
form
.
model1
())
ok_
(
u'value="
%
s"'
%
as_unicode
(
model
.
id
)
in
form
.
model1
())
# Check querying
client
=
app
.
test_client
()
req
=
client
.
get
(
u'/admin/view/ajax/lookup/?name=model1&query=foo'
)
eq_
(
req
.
data
,
u'[["
%
s", "foo"]]'
%
model2
.
id
)
# Check submitting
client
.
post
(
'/admin/view/new/'
,
data
=
{
u'model1'
:
as_unicode
(
model
.
id
)})
mdl
=
Model2
.
objects
.
first
()
ok_
(
mdl
is
not
None
)
ok_
(
mdl
.
model1
is
not
None
)
eq_
(
mdl
.
model1
.
id
,
model
.
id
)
eq_
(
mdl
.
model1
.
test1
,
u'first'
)
flask_admin/tests/sqlamodel/test_basic.py
View file @
efcc49ed
...
@@ -698,7 +698,8 @@ def test_ajax_fk():
...
@@ -698,7 +698,8 @@ def test_ajax_fk():
ok_
(
u'model1'
in
view
.
_form_ajax_refs
)
ok_
(
u'model1'
in
view
.
_form_ajax_refs
)
model
=
Model1
(
u'first'
)
model
=
Model1
(
u'first'
)
db
.
session
.
add_all
([
model
,
Model1
(
u'foo'
,
u'bar'
)])
model2
=
Model1
(
u'foo'
,
u'bar'
)
db
.
session
.
add_all
([
model
,
model2
])
db
.
session
.
commit
()
db
.
session
.
commit
()
# Check loader
# Check loader
...
@@ -719,16 +720,17 @@ def test_ajax_fk():
...
@@ -719,16 +720,17 @@ def test_ajax_fk():
eq_
(
form
.
model1
.
__class__
.
__name__
,
u'AjaxSelectField'
)
eq_
(
form
.
model1
.
__class__
.
__name__
,
u'AjaxSelectField'
)
with
app
.
test_request_context
(
'/admin/view/'
):
with
app
.
test_request_context
(
'/admin/view/'
):
ok_
(
u'value="
null"'
in
form
.
model1
())
ok_
(
u'value="
"'
not
in
form
.
model1
())
form
.
model1
.
data
=
model
form
.
model1
.
data
=
model
ok_
(
u'value="[1, "first"]"'
in
form
.
model1
())
ok_
(
u'data-json="[
%
s, "first"]"'
%
model
.
id
in
form
.
model1
())
ok_
(
u'value="1"'
in
form
.
model1
())
# Check querying
# Check querying
client
=
app
.
test_client
()
client
=
app
.
test_client
()
req
=
client
.
get
(
u'/admin/view/ajax/lookup/?name=model1&query=foo'
)
req
=
client
.
get
(
u'/admin/view/ajax/lookup/?name=model1&query=foo'
)
eq_
(
req
.
data
,
u'[[
2, "foo"]]'
)
eq_
(
req
.
data
,
u'[[
%
s, "foo"]]'
%
model2
.
id
)
# Check submitting
# Check submitting
req
=
client
.
post
(
'/admin/view/new/'
,
data
=
{
u'model1'
:
as_unicode
(
model
.
id
)})
req
=
client
.
post
(
'/admin/view/new/'
,
data
=
{
u'model1'
:
as_unicode
(
model
.
id
)})
...
@@ -738,3 +740,67 @@ def test_ajax_fk():
...
@@ -738,3 +740,67 @@ def test_ajax_fk():
ok_
(
mdl
.
model1
is
not
None
)
ok_
(
mdl
.
model1
is
not
None
)
eq_
(
mdl
.
model1
.
id
,
model
.
id
)
eq_
(
mdl
.
model1
.
id
,
model
.
id
)
eq_
(
mdl
.
model1
.
test1
,
u'first'
)
eq_
(
mdl
.
model1
.
test1
,
u'first'
)
def
test_ajax_fk_multi
():
app
,
db
,
admin
=
setup
()
class
Model1
(
db
.
Model
):
__tablename__
=
'model1'
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
)
name
=
db
.
Column
(
db
.
String
(
20
))
def
__str__
(
self
):
return
self
.
name
table
=
db
.
Table
(
'm2m'
,
db
.
Model
.
metadata
,
db
.
Column
(
'model1_id'
,
db
.
Integer
,
db
.
ForeignKey
(
'model1.id'
)),
db
.
Column
(
'model2_id'
,
db
.
Integer
,
db
.
ForeignKey
(
'model2.id'
))
)
class
Model2
(
db
.
Model
):
__tablename__
=
'model2'
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
)
name
=
db
.
Column
(
db
.
String
(
20
))
model1_id
=
db
.
Column
(
db
.
Integer
(),
db
.
ForeignKey
(
Model1
.
id
))
model1
=
db
.
relationship
(
Model1
,
backref
=
'models2'
,
secondary
=
table
)
db
.
create_all
()
view
=
CustomModelView
(
Model2
,
db
.
session
,
url
=
'view'
,
form_ajax_refs
=
{
'model1'
:
(
'name'
,)
}
)
admin
.
add_view
(
view
)
ok_
(
u'model1'
in
view
.
_form_ajax_refs
)
model
=
Model1
(
name
=
u'first'
)
db
.
session
.
add_all
([
model
,
Model1
(
name
=
u'foo'
)])
db
.
session
.
commit
()
# Check form generation
form
=
view
.
create_form
()
eq_
(
form
.
model1
.
__class__
.
__name__
,
u'AjaxSelectMultipleField'
)
with
app
.
test_request_context
(
'/admin/view/'
):
print
form
.
model1
()
ok_
(
u'data-json="[]"'
in
form
.
model1
())
form
.
model1
.
data
=
[
model
]
ok_
(
u'data-json="[[1, "first"]]"'
in
form
.
model1
())
# Check submitting
client
=
app
.
test_client
()
client
.
post
(
'/admin/view/new/'
,
data
=
{
u'model1'
:
as_unicode
(
model
.
id
)})
mdl
=
db
.
session
.
query
(
Model2
)
.
first
()
ok_
(
mdl
is
not
None
)
ok_
(
mdl
.
model1
is
not
None
)
eq_
(
len
(
mdl
.
model1
),
1
)
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