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
9344f9a0
Commit
9344f9a0
authored
Aug 26, 2013
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Peewee backend support
parent
efcc49ed
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
172 additions
and
8 deletions
+172
-8
ajax.py
flask_admin/contrib/mongoengine/ajax.py
+1
-1
ajax.py
flask_admin/contrib/peewee/ajax.py
+49
-0
form.py
flask_admin/contrib/peewee/form.py
+15
-2
view.py
flask_admin/contrib/peewee/view.py
+28
-3
ajax.py
flask_admin/contrib/sqla/ajax.py
+1
-1
test_basic.py
flask_admin/tests/peeweemodel/test_basic.py
+78
-1
No files found.
flask_admin/contrib/mongoengine/ajax.py
View file @
9344f9a0
...
...
@@ -32,7 +32,7 @@ class QueryAjaxModelLoader(AjaxModelLoader):
criteria
=
None
for
field
in
self
.
fields
:
flt
=
{
'
%
s__icontains'
%
field
.
name
:
term
}
flt
=
{
u
'
%
s__icontains'
%
field
.
name
:
term
}
if
not
criteria
:
criteria
=
mongoengine
.
Q
(
**
flt
)
...
...
flask_admin/contrib/peewee/ajax.py
0 → 100644
View file @
9344f9a0
import
mongoengine
from
flask.ext.admin._compat
import
as_unicode
from
flask.ext.admin.model.ajax
import
AjaxModelLoader
,
DEFAULT_PAGE_SIZE
from
.tools
import
get_primary_key
class
QueryAjaxModelLoader
(
AjaxModelLoader
):
def
__init__
(
self
,
name
,
model
,
fields
):
"""
Constructor.
:param fields:
Fields to run query against
"""
super
(
QueryAjaxModelLoader
,
self
)
.
__init__
(
name
)
self
.
model
=
model
self
.
fields
=
fields
self
.
pk
=
get_primary_key
(
model
)
def
format
(
self
,
model
):
if
not
model
:
return
None
return
(
getattr
(
model
,
self
.
pk
),
as_unicode
(
model
))
def
get_one
(
self
,
pk
):
return
self
.
model
.
get
(
**
{
self
.
pk
:
pk
})
def
get_list
(
self
,
term
,
offset
=
0
,
limit
=
DEFAULT_PAGE_SIZE
):
query
=
self
.
model
.
select
()
stmt
=
None
for
field
in
self
.
fields
:
q
=
field
**
(
u'
%%%
s
%%
'
%
term
)
if
stmt
is
None
:
stmt
=
q
else
:
stmt
|=
q
query
=
query
.
where
(
stmt
)
if
offset
:
query
=
query
.
offset
(
offset
)
return
list
(
query
.
limit
(
limit
)
.
execute
())
flask_admin/contrib/peewee/form.py
View file @
9344f9a0
...
...
@@ -8,7 +8,7 @@ from wtfpeewee.orm import ModelConverter, model_form
from
flask.ext.admin
import
form
from
flask.ext.admin._compat
import
iteritems
,
itervalues
from
flask.ext.admin.model.form
import
InlineFormAdmin
,
InlineModelConverterBase
from
flask.ext.admin.model.fields
import
InlineModelFormField
,
InlineFieldList
from
flask.ext.admin.model.fields
import
InlineModelFormField
,
InlineFieldList
,
AjaxSelectField
from
.tools
import
get_primary_key
...
...
@@ -80,13 +80,26 @@ class InlineModelFormList(InlineFieldList):
class
CustomModelConverter
(
ModelConverter
):
def
__init__
(
self
,
additional
=
None
):
def
__init__
(
self
,
view
,
additional
=
None
):
super
(
CustomModelConverter
,
self
)
.
__init__
(
additional
)
self
.
view
=
view
self
.
converters
[
PrimaryKeyField
]
=
self
.
handle_pk
self
.
converters
[
DateTimeField
]
=
self
.
handle_datetime
self
.
converters
[
DateField
]
=
self
.
handle_date
self
.
converters
[
TimeField
]
=
self
.
handle_time
def
handle_foreign_key
(
self
,
model
,
field
,
**
kwargs
):
loader
=
self
.
view
.
_form_ajax_refs
.
get
(
field
.
name
)
if
loader
:
if
field
.
null
:
kwargs
[
'allow_blank'
]
=
True
return
field
.
name
,
AjaxSelectField
(
loader
,
**
kwargs
)
return
super
(
CustomModelConverter
,
self
)
.
handle_foreign_key
(
model
,
field
,
**
kwargs
)
def
handle_pk
(
self
,
model
,
field
,
**
kwargs
):
kwargs
[
'validators'
]
=
[]
return
field
.
name
,
fields
.
HiddenField
(
**
kwargs
)
...
...
flask_admin/contrib/peewee/view.py
View file @
9344f9a0
...
...
@@ -2,7 +2,6 @@ import logging
from
flask
import
flash
from
flask.ext.admin
import
form
from
flask.ext.admin._compat
import
string_types
from
flask.ext.admin.babel
import
gettext
,
ngettext
,
lazy_gettext
from
flask.ext.admin.model
import
BaseModelView
...
...
@@ -11,8 +10,10 @@ from peewee import PrimaryKeyField, ForeignKeyField, Field, CharField, TextField
from
flask.ext.admin.actions
import
action
from
flask.ext.admin.contrib.peewee
import
filters
from
.form
import
get_form
,
CustomModelConverter
,
InlineModelConverter
,
save_inline
from
.tools
import
get_primary_key
,
parse_like_term
from
.ajax
import
QueryAjaxModelLoader
class
ModelView
(
BaseModelView
):
...
...
@@ -217,7 +218,7 @@ class ModelView(BaseModelView):
return
isinstance
(
filter
,
filters
.
BasePeeweeFilter
)
def
scaffold_form
(
self
):
form_class
=
get_form
(
self
.
model
,
self
.
model_form_converter
(),
form_class
=
get_form
(
self
.
model
,
self
.
model_form_converter
(
self
),
base_class
=
self
.
form_base_class
,
only
=
self
.
form_columns
,
exclude
=
self
.
form_excluded_columns
,
...
...
@@ -230,7 +231,7 @@ class ModelView(BaseModelView):
return
form_class
def
scaffold_inline_form_models
(
self
,
form_class
):
converter
=
self
.
model_form_converter
()
converter
=
self
.
model_form_converter
(
self
)
inline_converter
=
self
.
inline_model_form_converter
(
self
)
for
m
in
self
.
inline_models
:
...
...
@@ -241,6 +242,30 @@ class ModelView(BaseModelView):
return
form_class
# AJAX foreignkey support
def
_create_ajax_loader
(
self
,
name
,
fields
):
prop
=
getattr
(
self
.
model
,
name
,
None
)
if
prop
is
None
:
raise
ValueError
(
'Model
%
s does not have field
%
s.'
%
(
self
.
model
,
name
))
# TODO: Check for field
remote_model
=
prop
.
rel_model
remote_fields
=
[]
for
field
in
fields
:
if
isinstance
(
field
,
string_types
):
attr
=
getattr
(
remote_model
,
field
,
None
)
if
not
attr
:
raise
ValueError
(
'
%
s.
%
s does not exist.'
%
(
remote_model
,
field
))
remote_fields
.
append
(
attr
)
else
:
remote_fields
.
append
(
field
)
return
QueryAjaxModelLoader
(
name
,
remote_model
,
remote_fields
)
def
_handle_join
(
self
,
query
,
field
,
joins
):
if
field
.
model_class
!=
self
.
model
:
model_name
=
field
.
model_class
.
__name__
...
...
flask_admin/contrib/sqla/ajax.py
View file @
9344f9a0
...
...
@@ -36,7 +36,7 @@ class QueryAjaxModelLoader(AjaxModelLoader):
def
get_list
(
self
,
term
,
offset
=
0
,
limit
=
DEFAULT_PAGE_SIZE
):
query
=
self
.
session
.
query
(
self
.
model
)
filters
=
(
field
.
like
(
'
%%%
s
%%
'
%
term
)
for
field
in
self
.
fields
)
filters
=
(
field
.
like
(
u
'
%%%
s
%%
'
%
term
)
for
field
in
self
.
fields
)
query
=
query
.
filter
(
or_
(
*
filters
))
return
query
.
offset
(
offset
)
.
limit
(
limit
)
.
all
()
flask_admin/tests/peeweemodel/test_basic.py
View file @
9344f9a0
...
...
@@ -2,7 +2,7 @@ from nose.tools import eq_, ok_
from
nose.plugins.skip
import
SkipTest
# Skip test on PY3
from
flask.ext.admin._compat
import
PY2
from
flask.ext.admin._compat
import
PY2
,
as_unicode
if
not
PY2
:
raise
SkipTest
(
'Peewee is not Python 3 compatible'
)
...
...
@@ -194,3 +194,80 @@ def test_custom_form_base():
create_form
=
view
.
create_form
()
ok_
(
isinstance
(
create_form
,
TestForm
))
def
test_ajax_fk
():
app
,
db
,
admin
=
setup
()
class
BaseModel
(
peewee
.
Model
):
class
Meta
:
database
=
db
class
Model1
(
BaseModel
):
test1
=
peewee
.
CharField
(
max_length
=
20
)
test2
=
peewee
.
CharField
(
max_length
=
20
)
def
__str__
(
self
):
return
self
.
test1
class
Model2
(
BaseModel
):
model1
=
peewee
.
ForeignKeyField
(
Model1
)
Model1
.
create_table
()
Model2
.
create_table
()
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'
,
test2
=
u''
)
model
.
save
()
model2
=
Model1
(
test1
=
u'foo'
,
test2
=
u'bar'
)
model2
.
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
.
select
()
.
first
()
ok_
(
mdl
is
not
None
)
ok_
(
mdl
.
model1
is
not
None
)
eq_
(
mdl
.
model1
.
id
,
model
.
id
)
eq_
(
mdl
.
model1
.
test1
,
u'first'
)
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