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
675c2846
Commit
675c2846
authored
Dec 29, 2015
by
Paul Brown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add hstore column converter to SQLA backend
parent
572f1d39
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
114 additions
and
8 deletions
+114
-8
.travis.yml
.travis.yml
+2
-1
fields.py
flask_admin/contrib/sqla/fields.py
+49
-5
form.py
flask_admin/contrib/sqla/form.py
+8
-1
fields.py
flask_admin/model/fields.py
+1
-1
__init__.py
flask_admin/tests/sqla/__init__.py
+12
-0
test_postgres.py
flask_admin/tests/sqla/test_postgres.py
+42
-0
No files found.
.travis.yml
View file @
675c2846
...
...
@@ -16,7 +16,8 @@ services:
before_script
:
-
psql -U postgres -c 'CREATE DATABASE flask_admin_test;'
-
psql -U postgres -c "CREATE EXTENSION postgis;" flask_admin_test
-
psql -U postgres -c 'CREATE EXTENSION postgis;' flask_admin_test
-
psql -U postgres -c 'CREATE EXTENSION hstore;' flask_admin_test
install
:
-
pip install "wtforms<$WTFORMS_VERSION.99"
...
...
flask_admin/contrib/sqla/fields.py
View file @
675c2846
...
...
@@ -4,15 +4,19 @@
import
operator
from
wtforms
import
widgets
from
wtforms.fields
import
SelectFieldBase
from
wtforms.fields
import
SelectFieldBase
,
TextField
from
wtforms.validators
import
ValidationError
try
:
from
wtforms.fields
import
_unset_value
as
unset_value
except
ImportError
:
from
wtforms.utils
import
unset_value
from
.tools
import
get_primary_key
from
flask_admin._compat
import
text_type
,
string_types
from
flask_admin.form
import
FormOpts
from
flask_admin._compat
import
text_type
,
string_types
,
iteritems
from
flask_admin.form
import
FormOpts
,
BaseForm
from
flask_admin.model.fields
import
InlineFieldList
,
InlineModelFormField
from
flask_admin.model.widgets
import
InlineFormWidget
from
flask_admin.babel
import
lazy_gettext
try
:
from
sqlalchemy.orm.util
import
identity_key
...
...
@@ -178,6 +182,46 @@ class QuerySelectMultipleField(QuerySelectField):
raise
ValidationError
(
self
.
gettext
(
u'Not a valid choice'
))
class
HstoreForm
(
BaseForm
):
""" Form used in InlineFormField/InlineHstoreList for HSTORE columns """
key
=
TextField
(
lazy_gettext
(
'Key'
))
value
=
TextField
(
lazy_gettext
(
'Value'
))
class
KeyValue
(
object
):
""" Used by InlineHstoreList to simulate a key and a value field instead of
the single HSTORE column. """
def
__init__
(
self
,
key
=
None
,
value
=
None
):
self
.
key
=
key
self
.
value
=
value
class
InlineHstoreList
(
InlineFieldList
):
""" Version of InlineFieldList for use with Postgres HSTORE columns """
def
process
(
self
,
formdata
,
data
=
unset_value
):
""" SQLAlchemy returns a dict for HSTORE columns, but WTForms cannot
process a dict. This overrides `process` to convert the dict
returned by SQLAlchemy to a list of classes before processing. """
if
isinstance
(
data
,
dict
):
data
=
[
KeyValue
(
k
,
v
)
for
k
,
v
in
iteritems
(
data
)]
super
(
InlineHstoreList
,
self
)
.
process
(
formdata
,
data
)
def
populate_obj
(
self
,
obj
,
name
):
""" Combines each FormField key/value into a dictionary for storage """
_fake
=
type
(
str
(
'_fake'
),
(
object
,
),
{})
output
=
{}
for
form_field
in
self
.
entries
:
if
not
self
.
should_delete
(
form_field
):
fake_obj
=
_fake
()
fake_obj
.
data
=
KeyValue
()
form_field
.
populate_obj
(
fake_obj
,
'data'
)
output
[
fake_obj
.
data
.
key
]
=
fake_obj
.
data
.
value
setattr
(
obj
,
name
,
output
)
class
InlineModelFormList
(
InlineFieldList
):
"""
Customized inline model form list field.
...
...
flask_admin/contrib/sqla/form.py
View file @
675c2846
...
...
@@ -12,7 +12,9 @@ from flask_admin._backwards import get_property
from
flask_admin._compat
import
iteritems
from
.validators
import
Unique
from
.fields
import
QuerySelectField
,
QuerySelectMultipleField
,
InlineModelFormList
from
.fields
import
(
QuerySelectField
,
QuerySelectMultipleField
,
InlineModelFormList
,
InlineHstoreList
,
HstoreForm
)
from
flask_admin.model.fields
import
InlineFormField
from
.tools
import
has_multiple_pks
,
filter_foreign_columns
from
.ajax
import
create_ajax_loader
...
...
@@ -350,6 +352,11 @@ class AdminModelConverter(ModelConverterBase):
def
conv_ARRAY
(
self
,
field_args
,
**
extra
):
return
form
.
Select2TagsField
(
save_as_list
=
True
,
**
field_args
)
@
converts
(
'HSTORE'
)
def
conv_HSTORE
(
self
,
field_args
,
**
extra
):
inner_form
=
field_args
.
pop
(
'form'
,
HstoreForm
)
return
InlineHstoreList
(
InlineFormField
(
inner_form
),
**
field_args
)
def
_resolve_prop
(
prop
):
"""
...
...
flask_admin/model/fields.py
View file @
675c2846
...
...
@@ -40,7 +40,7 @@ class InlineFieldList(FieldList):
def
display_row_controls
(
self
,
field
):
return
True
def
process
(
self
,
formdata
,
data
=
Non
e
):
def
process
(
self
,
formdata
,
data
=
unset_valu
e
):
res
=
super
(
InlineFieldList
,
self
)
.
process
(
formdata
,
data
)
# Postprocess - contribute flag
...
...
flask_admin/tests/sqla/__init__.py
View file @
675c2846
...
...
@@ -14,3 +14,15 @@ def setup():
admin
=
Admin
(
app
)
return
app
,
db
,
admin
def
setup_postgres
():
app
=
Flask
(
__name__
)
app
.
config
[
'SECRET_KEY'
]
=
'1'
app
.
config
[
'CSRF_ENABLED'
]
=
False
app
.
config
[
'SQLALCHEMY_DATABASE_URI'
]
=
'postgresql://localhost/flask_admin_test'
app
.
config
[
'SQLALCHEMY_ECHO'
]
=
True
db
=
SQLAlchemy
(
app
)
admin
=
Admin
(
app
)
return
app
,
db
,
admin
flask_admin/tests/sqla/test_postgres.py
0 → 100644
View file @
675c2846
from
nose.tools
import
eq_
,
ok_
from
.
import
setup_postgres
from
.test_basic
import
CustomModelView
from
sqlalchemy.dialects.postgresql
import
HSTORE
def
test_hstore
():
app
,
db
,
admin
=
setup_postgres
()
class
Model
(
db
.
Model
):
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
,
autoincrement
=
True
)
hstore_test
=
db
.
Column
(
HSTORE
)
db
.
create_all
()
view
=
CustomModelView
(
Model
,
db
.
session
)
admin
.
add_view
(
view
)
client
=
app
.
test_client
()
rv
=
client
.
get
(
'/admin/model/'
)
eq_
(
rv
.
status_code
,
200
)
rv
=
client
.
post
(
'/admin/model/new/'
,
data
=
{
'hstore_test-0-key'
:
'test_val1'
,
'hstore_test-0-value'
:
'test_val2'
})
eq_
(
rv
.
status_code
,
302
)
rv
=
client
.
get
(
'/admin/model/'
)
eq_
(
rv
.
status_code
,
200
)
data
=
rv
.
data
.
decode
(
'utf-8'
)
ok_
(
'test_val1'
in
data
)
ok_
(
'test_val2'
in
data
)
rv
=
client
.
get
(
'/admin/model/edit/?id=1'
)
eq_
(
rv
.
status_code
,
200
)
data
=
rv
.
data
.
decode
(
'utf-8'
)
ok_
(
'test_val1'
in
data
)
ok_
(
'test_val2'
in
data
)
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