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
53c68c72
Commit
53c68c72
authored
Jun 13, 2013
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Python 3 fixes.
parent
f6894398
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
149 additions
and
71 deletions
+149
-71
simple.py
examples/sqla/simple.py
+5
-5
_compat.py
flask_admin/_compat.py
+65
-0
actions.py
flask_admin/actions.py
+4
-4
base.py
flask_admin/base.py
+2
-3
view.py
flask_admin/contrib/mongoengine/view.py
+5
-4
form.py
flask_admin/contrib/peeweemodel/form.py
+2
-2
view.py
flask_admin/contrib/peeweemodel/view.py
+5
-5
view.py
flask_admin/contrib/pymongo/view.py
+2
-2
fields.py
flask_admin/contrib/sqlamodel/fields.py
+6
-5
validators.py
flask_admin/contrib/sqlamodel/validators.py
+2
-1
view.py
flask_admin/contrib/sqlamodel/view.py
+10
-9
form.py
flask_admin/form.py
+6
-2
base.py
flask_admin/model/base.py
+3
-4
fields.py
flask_admin/model/fields.py
+5
-4
filters.py
flask_admin/model/filters.py
+2
-1
form.py
flask_admin/model/form.py
+2
-1
typefmt.py
flask_admin/model/typefmt.py
+2
-1
form.js
flask_admin/static/js/form.js
+2
-2
inline_list_base.html
flask_admin/templates/admin/model/inline_list_base.html
+9
-10
test_basic.py
flask_admin/tests/peeweemodel/test_basic.py
+2
-1
test_basic.py
flask_admin/tests/sqlamodel/test_basic.py
+3
-1
test_model.py
flask_admin/tests/test_model.py
+2
-2
tools.py
flask_admin/tools.py
+3
-0
requirements.txt
requirements.txt
+0
-1
setup.py
setup.py
+0
-1
No files found.
examples/sqla/simple.py
View file @
53c68c72
...
...
@@ -26,7 +26,7 @@ class User(db.Model):
email
=
db
.
Column
(
db
.
String
(
120
),
unique
=
True
)
# Required for administrative interface
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
self
.
username
...
...
@@ -48,7 +48,7 @@ class Post(db.Model):
tags
=
db
.
relationship
(
'Tag'
,
secondary
=
post_tags_table
)
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
self
.
title
...
...
@@ -56,7 +56,7 @@ class Tag(db.Model):
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
)
name
=
db
.
Column
(
db
.
Unicode
(
64
))
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
self
.
name
...
...
@@ -69,7 +69,7 @@ class UserInfo(db.Model):
user_id
=
db
.
Column
(
db
.
Integer
(),
db
.
ForeignKey
(
User
.
id
))
user
=
db
.
relationship
(
User
,
backref
=
'info'
)
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
'
%
s -
%
s'
%
(
self
.
key
,
self
.
value
)
...
...
@@ -79,7 +79,7 @@ class Tree(db.Model):
parent_id
=
db
.
Column
(
db
.
Integer
,
db
.
ForeignKey
(
'tree.id'
))
parent
=
db
.
relationship
(
'Tree'
,
remote_side
=
[
id
],
backref
=
'children'
)
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
self
.
name
...
...
flask_admin/_compat.py
0 → 100644
View file @
53c68c72
# -*- coding: utf-8 -*-
"""
flask.ext.admin._compat
~~~~~~~~~~~~~~~~~~~~~~~
Some py2/py3 compatibility support based on a stripped down
version of six so we don't have to depend on a specific version
of it.
:copyright: (c) 2013 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
import
sys
PY2
=
sys
.
version_info
[
0
]
==
2
if
not
PY2
:
text_type
=
str
string_types
=
(
str
,)
integer_types
=
(
int
,
)
iterkeys
=
lambda
d
:
iter
(
d
.
keys
())
itervalues
=
lambda
d
:
iter
(
d
.
values
())
iteritems
=
lambda
d
:
iter
(
d
.
items
())
def
as_unicode
(
text
):
return
str
(
text
)
from
functools
import
reduce
else
:
unicode_type
=
unicode
text_type
=
unicode
string_types
=
(
str
,
unicode
)
integer_types
=
(
int
,
long
)
iterkeys
=
lambda
d
:
d
.
iterkeys
()
itervalues
=
lambda
d
:
d
.
itervalues
()
iteritems
=
lambda
d
:
d
.
iteritems
()
def
as_unicode
(
text
):
return
unicode
(
text
)
reduce
=
__builtin__
.
reduce
def
with_metaclass
(
meta
,
*
bases
):
# This requires a bit of explanation: the basic idea is to make a
# dummy metaclass for one level of class instantiation that replaces
# itself with the actual metaclass. Because of internal type checks
# we also need to make sure that we downgrade the custom metaclass
# for one level to something closer to type (that's why __call__ and
# __init__ comes back from type etc.).
#
# This has the advantage over six.with_metaclass in that it does not
# introduce dummy classes into the final MRO.
class
metaclass
(
meta
):
__call__
=
type
.
__call__
__init__
=
type
.
__init__
def
__new__
(
cls
,
name
,
this_bases
,
d
):
if
this_bases
is
None
:
return
type
.
__new__
(
cls
,
name
,
(),
d
)
return
meta
(
name
,
bases
,
d
)
return
metaclass
(
'temporary_class'
,
None
,
{})
flask_admin/actions.py
View file @
53c68c72
from
flask
import
request
,
url_for
,
redirect
from
flask.ext.admin
.tools
import
get_dict_attr
from
flask.ext.admin
import
tools
,
_compat
def
action
(
name
,
text
,
confirmation
=
None
):
...
...
@@ -53,7 +53,7 @@ class ActionsMixin(object):
self
.
_actions_data
=
{}
for
p
in
dir
(
self
):
attr
=
get_dict_attr
(
self
,
p
)
attr
=
tools
.
get_dict_attr
(
self
,
p
)
if
hasattr
(
attr
,
'_action'
):
name
,
text
,
desc
=
attr
.
_action
...
...
@@ -85,12 +85,12 @@ class ActionsMixin(object):
name
,
text
=
act
if
self
.
is_action_allowed
(
name
):
text
=
unicode
(
text
)
text
=
_compat
.
as_
unicode
(
text
)
actions
.
append
((
name
,
text
))
confirmation
=
self
.
_actions_data
[
name
][
2
]
if
confirmation
:
actions_confirmation
[
name
]
=
unicod
e
(
confirmation
)
actions_confirmation
[
name
]
=
_compat
.
text_typ
e
(
confirmation
)
return
actions
,
actions_confirmation
...
...
flask_admin/base.py
View file @
53c68c72
from
functools
import
wraps
from
re
import
sub
import
six
from
flask
import
Blueprint
,
render_template
,
url_for
,
abort
,
g
from
flask.ext.admin
import
babel
from
flask.ext.admin
import
babel
,
_compat
from
flask.ext.admin
import
helpers
as
h
...
...
@@ -95,7 +94,7 @@ class BaseMeta(object):
pass
class
BaseView
(
six
.
with_metaclass
(
AdminViewMeta
,
BaseMeta
)):
class
BaseView
(
_compat
.
with_metaclass
(
AdminViewMeta
,
BaseMeta
)):
"""
Base administrative view.
...
...
flask_admin/contrib/mongoengine/view.py
View file @
53c68c72
...
...
@@ -4,6 +4,7 @@ from flask import flash
from
flask.ext.admin.babel
import
gettext
,
ngettext
,
lazy_gettext
from
flask.ext.admin.model
import
BaseModelView
from
flask.ext.admin
import
_compat
import
mongoengine
from
bson.objectid
import
ObjectId
...
...
@@ -115,7 +116,7 @@ class ModelView(BaseModelView):
if
model
is
None
:
model
=
self
.
model
return
sorted
(
model
.
_fields
.
iteritems
(
),
key
=
lambda
n
:
n
[
1
]
.
creation_counter
)
return
sorted
(
_compat
.
iteritems
(
model
.
_fields
),
key
=
lambda
n
:
n
[
1
]
.
creation_counter
)
def
scaffold_pk
(
self
):
# MongoEngine models have predefined 'id' as a key
...
...
@@ -171,7 +172,7 @@ class ModelView(BaseModelView):
"""
if
self
.
column_searchable_list
:
for
p
in
self
.
column_searchable_list
:
if
isinstance
(
p
,
basestring
):
if
isinstance
(
p
,
_compat
.
string_types
):
p
=
self
.
model
.
_fields
.
get
(
p
)
if
p
is
None
:
...
...
@@ -195,7 +196,7 @@ class ModelView(BaseModelView):
:param name:
Either field name or field instance
"""
if
isinstance
(
name
,
basestring
):
if
isinstance
(
name
,
_compat
.
string_types
):
attr
=
self
.
model
.
_fields
.
get
(
name
)
else
:
attr
=
name
...
...
@@ -206,7 +207,7 @@ class ModelView(BaseModelView):
# Find name
visible_name
=
None
if
not
isinstance
(
name
,
basestring
):
if
not
isinstance
(
name
,
_compat
.
string_types
):
visible_name
=
self
.
get_column_name
(
attr
.
name
)
if
not
visible_name
:
...
...
flask_admin/contrib/peeweemodel/form.py
View file @
53c68c72
...
...
@@ -5,7 +5,7 @@ from peewee import (DateTimeField, DateField, TimeField,
from
wtfpeewee.orm
import
ModelConverter
,
model_form
from
flask.ext.admin
import
form
from
flask.ext.admin
import
form
,
_compat
from
flask.ext.admin.model.form
import
InlineFormAdmin
,
InlineModelConverterBase
from
flask.ext.admin.model.fields
import
InlineModelFormField
,
InlineFieldList
...
...
@@ -164,6 +164,6 @@ class InlineModelConverter(InlineModelConverterBase):
def
save_inline
(
form
,
model
):
for
_
,
f
in
form
.
_fields
.
iteritems
(
):
for
_
,
f
in
_compat
(
form
.
_fields
):
if
f
.
type
==
'InlineModelFormList'
:
f
.
save_related
(
model
)
flask_admin/contrib/peeweemodel/view.py
View file @
53c68c72
...
...
@@ -2,7 +2,7 @@ import logging
from
flask
import
flash
from
flask.ext.admin
import
form
from
flask.ext.admin
import
form
,
_compat
from
flask.ext.admin.babel
import
gettext
,
ngettext
,
lazy_gettext
from
flask.ext.admin.model
import
BaseModelView
...
...
@@ -173,7 +173,7 @@ class ModelView(BaseModelView):
def
init_search
(
self
):
if
self
.
column_searchable_list
:
for
p
in
self
.
column_searchable_list
:
if
isinstance
(
p
,
basestring
):
if
isinstance
(
p
,
_compat
.
string_types
):
p
=
getattr
(
self
.
model
,
p
)
field_type
=
type
(
p
)
...
...
@@ -189,7 +189,7 @@ class ModelView(BaseModelView):
return
bool
(
self
.
_search_fields
)
def
scaffold_filters
(
self
,
name
):
if
isinstance
(
name
,
basestring
):
if
isinstance
(
name
,
_compat
.
string_types
):
attr
=
getattr
(
self
.
model
,
name
,
None
)
else
:
attr
=
name
...
...
@@ -202,7 +202,7 @@ class ModelView(BaseModelView):
visible_name
=
'
%
s /
%
s'
%
(
self
.
get_column_name
(
attr
.
model_class
.
__name__
),
self
.
get_column_name
(
attr
.
name
))
else
:
if
not
isinstance
(
name
,
basestring
):
if
not
isinstance
(
name
,
_compat
.
string_types
):
visible_name
=
self
.
get_column_name
(
attr
.
name
)
else
:
visible_name
=
self
.
get_column_name
(
name
)
...
...
@@ -253,7 +253,7 @@ class ModelView(BaseModelView):
return
query
def
_order_by
(
self
,
query
,
joins
,
sort_field
,
sort_desc
):
if
isinstance
(
sort_field
,
basestring
):
if
isinstance
(
sort_field
,
_compat
.
string_types
):
field
=
getattr
(
self
.
model
,
sort_field
)
query
=
query
.
order_by
(
field
.
desc
()
if
sort_desc
else
field
.
asc
())
elif
isinstance
(
sort_field
,
Field
):
...
...
flask_admin/contrib/pymongo/view.py
View file @
53c68c72
...
...
@@ -5,8 +5,8 @@ from bson import ObjectId
from
bson.errors
import
InvalidId
from
flask
import
flash
from
jinja2
import
contextfunction
from
flask.ext.admin
import
_compat
from
flask.ext.admin.babel
import
gettext
,
ngettext
,
lazy_gettext
from
flask.ext.admin.model
import
BaseModelView
from
flask.ext.admin.actions
import
action
...
...
@@ -92,7 +92,7 @@ class ModelView(BaseModelView):
"""
if
self
.
column_searchable_list
:
for
p
in
self
.
column_searchable_list
:
if
not
isinstance
(
p
,
basestring
):
if
not
isinstance
(
p
,
_compat
.
string_types
):
raise
ValueError
(
'Expected string'
)
# TODO: Validation?
...
...
flask_admin/contrib/sqlamodel/fields.py
View file @
53c68c72
...
...
@@ -8,6 +8,7 @@ from wtforms.fields import SelectFieldBase
from
wtforms.validators
import
ValidationError
from
.tools
import
get_primary_key
from
flask.ext.admin
import
_compat
from
flask.ext.admin.model.fields
import
InlineFieldList
,
InlineModelFormField
...
...
@@ -63,14 +64,14 @@ class QuerySelectField(SelectFieldBase):
if
get_pk
is
None
:
if
not
has_identity_key
:
raise
Exception
(
'The sqlalchemy identity_key function could not be imported.'
)
raise
Exception
(
u
'The sqlalchemy identity_key function could not be imported.'
)
self
.
get_pk
=
get_pk_from_identity
else
:
self
.
get_pk
=
get_pk
if
get_label
is
None
:
self
.
get_label
=
lambda
x
:
x
elif
isinstance
(
get_label
,
basestring
):
elif
isinstance
(
get_label
,
_compat
.
string_types
):
self
.
get_label
=
operator
.
attrgetter
(
get_label
)
else
:
self
.
get_label
=
get_label
...
...
@@ -98,7 +99,7 @@ class QuerySelectField(SelectFieldBase):
if
self
.
_object_list
is
None
:
query
=
self
.
query
or
self
.
query_factory
()
get_pk
=
self
.
get_pk
self
.
_object_list
=
list
((
unicode
(
get_pk
(
obj
)),
obj
)
for
obj
in
query
)
self
.
_object_list
=
[(
_compat
.
as_unicode
(
get_pk
(
obj
)),
obj
)
for
obj
in
query
]
return
self
.
_object_list
def
iter_choices
(
self
):
...
...
@@ -177,7 +178,7 @@ class QuerySelectMultipleField(QuerySelectField):
obj_list
=
list
(
x
[
1
]
for
x
in
self
.
_get_object_list
())
for
v
in
self
.
data
:
if
v
not
in
obj_list
:
raise
ValidationError
(
self
.
gettext
(
'Not a valid choice'
))
raise
ValidationError
(
self
.
gettext
(
u
'Not a valid choice'
))
class
InlineModelFormList
(
InlineFieldList
):
...
...
@@ -238,4 +239,4 @@ class InlineModelFormList(InlineFieldList):
def
get_pk_from_identity
(
obj
):
# TODO: Remove me
cls
,
key
=
identity_key
(
instance
=
obj
)
return
u':'
.
join
(
unicode
(
x
)
for
x
in
key
)
return
u':'
.
join
(
_compat
.
as_
unicode
(
x
)
for
x
in
key
)
flask_admin/contrib/sqlamodel/validators.py
View file @
53c68c72
...
...
@@ -26,7 +26,8 @@ class Unique(object):
def
__call__
(
self
,
form
,
field
):
try
:
obj
=
(
self
.
db_session
.
query
(
self
.
model
)
.
filter
(
self
.
column
==
field
.
data
)
.
one
())
.
filter
(
self
.
column
==
field
.
data
)
.
one
())
if
not
hasattr
(
form
,
'_obj'
)
or
not
form
.
_obj
==
obj
:
if
self
.
message
is
None
:
...
...
flask_admin/contrib/sqlamodel/view.py
View file @
53c68c72
...
...
@@ -7,6 +7,7 @@ from sqlalchemy import or_, Column, func
from
flask
import
flash
from
flask.ext.admin
import
_compat
from
flask.ext.admin.tools
import
ObsoleteAttr
from
flask.ext.admin.babel
import
gettext
,
ngettext
,
lazy_gettext
from
flask.ext.admin.model
import
BaseModelView
...
...
@@ -348,7 +349,7 @@ class ModelView(BaseModelView):
return
columns
def
_get_columns_for_field
(
self
,
field
):
if
isinstance
(
field
,
basestring
):
if
isinstance
(
field
,
_compat
.
string_types
):
attr
=
getattr
(
self
.
model
,
field
,
None
)
if
field
is
None
:
...
...
@@ -410,7 +411,7 @@ class ModelView(BaseModelView):
"""
join_tables
=
[]
if
isinstance
(
name
,
basestring
):
if
isinstance
(
name
,
_compat
.
string_types
):
model
=
self
.
model
for
attribute
in
name
.
split
(
'.'
):
...
...
@@ -474,7 +475,7 @@ class ModelView(BaseModelView):
self
.
get_column_name
(
column
.
name
)
)
else
:
if
not
isinstance
(
name
,
basestring
):
if
not
isinstance
(
name
,
_compat
.
string_types
):
visible_name
=
self
.
get_column_name
(
name
.
property
.
key
)
else
:
visible_name
=
self
.
get_column_name
(
name
)
...
...
@@ -596,7 +597,7 @@ class ModelView(BaseModelView):
"""
# TODO: Preprocessing for joins
# Try to handle it as a string
if
isinstance
(
sort_field
,
basestring
):
if
isinstance
(
sort_field
,
_compat
.
string_types
):
# Create automatic join against a table if column name
# contains dot.
if
'.'
in
sort_field
:
...
...
@@ -637,7 +638,7 @@ class ModelView(BaseModelView):
if
order
is
not
None
:
field
,
direction
=
order
if
isinstance
(
field
,
basestring
):
if
isinstance
(
field
,
_compat
.
string_types
):
field
=
getattr
(
self
.
model
,
field
)
return
field
,
direction
...
...
@@ -764,7 +765,7 @@ class ModelView(BaseModelView):
self
.
session
.
add
(
model
)
self
.
on_model_change
(
form
,
model
)
self
.
session
.
commit
()
except
Exception
,
ex
:
except
Exception
as
ex
:
flash
(
gettext
(
'Failed to create model.
%(error)
s'
,
error
=
str
(
ex
)),
'error'
)
logging
.
exception
(
'Failed to create model'
)
self
.
session
.
rollback
()
...
...
@@ -787,7 +788,7 @@ class ModelView(BaseModelView):
form
.
populate_obj
(
model
)
self
.
on_model_change
(
form
,
model
)
self
.
session
.
commit
()
except
Exception
,
ex
:
except
Exception
as
ex
:
flash
(
gettext
(
'Failed to update model.
%(error)
s'
,
error
=
str
(
ex
)),
'error'
)
logging
.
exception
(
'Failed to update model'
)
self
.
session
.
rollback
()
...
...
@@ -810,7 +811,7 @@ class ModelView(BaseModelView):
self
.
session
.
delete
(
model
)
self
.
session
.
commit
()
return
True
except
Exception
,
ex
:
except
Exception
as
ex
:
flash
(
gettext
(
'Failed to delete model.
%(error)
s'
,
error
=
str
(
ex
)),
'error'
)
logging
.
exception
(
'Failed to delete model'
)
self
.
session
.
rollback
()
...
...
@@ -848,5 +849,5 @@ class ModelView(BaseModelView):
'
%(count)
s models were successfully deleted.'
,
count
,
count
=
count
))
except
Exception
,
ex
:
except
Exception
as
ex
:
flash
(
gettext
(
'Failed to delete models.
%(error)
s'
,
error
=
str
(
ex
)),
'error'
)
flask_admin/form.py
View file @
53c68c72
...
...
@@ -5,11 +5,15 @@ from wtforms import form, fields, widgets
from
flask.globals
import
_request_ctx_stack
from
flask.ext.admin.babel
import
gettext
,
ngettext
from
flask.ext.admin
import
helpers
as
h
from
flask.ext.admin
import
_compat
# TODO: Use flask.ext.wtf if possible
class
BaseForm
(
form
.
Form
):
pass
def
__init__
(
self
,
formdata
=
None
,
obj
=
None
,
prefix
=
u''
,
**
kwargs
):
self
.
_obj
=
obj
super
(
BaseForm
,
self
)
.
__init__
(
formdata
=
formdata
,
obj
=
obj
,
prefix
=
prefix
,
**
kwargs
)
class
TimeField
(
fields
.
Field
):
...
...
@@ -88,7 +92,7 @@ class Select2Field(fields.SelectField):
"""
widget
=
Select2Widget
()
def
__init__
(
self
,
label
=
None
,
validators
=
None
,
coerce
=
unicod
e
,
def
__init__
(
self
,
label
=
None
,
validators
=
None
,
coerce
=
_compat
.
text_typ
e
,
choices
=
None
,
allow_blank
=
False
,
blank_text
=
None
,
**
kwargs
):
super
(
Select2Field
,
self
)
.
__init__
(
label
,
validators
,
coerce
,
choices
,
**
kwargs
...
...
flask_admin/model/base.py
View file @
53c68c72
...
...
@@ -10,7 +10,7 @@ from flask.ext.admin.base import BaseView, expose
from
flask.ext.admin.tools
import
rec_getattr
,
ObsoleteAttr
from
flask.ext.admin.model
import
filters
,
typefmt
from
flask.ext.admin.actions
import
ActionsMixin
from
flask.ext.admin
import
get_form_data
,
validate_form_on_submit
from
flask.ext.admin
.helpers
import
get_form_data
,
validate_form_on_submit
class
BaseModelView
(
BaseView
,
ActionsMixin
):
...
...
@@ -937,7 +937,7 @@ class BaseModelView(BaseView, ActionsMixin):
search
,
filters
)
# Calculate number of pages
num_pages
=
count
/
self
.
page_size
num_pages
=
count
/
/
self
.
page_size
if
count
%
self
.
page_size
!=
0
:
num_pages
+=
1
...
...
@@ -1014,8 +1014,7 @@ class BaseModelView(BaseView, ActionsMixin):
# Actions
actions
=
actions
,
actions_confirmation
=
actions_confirmation
)
actions_confirmation
=
actions_confirmation
)
@
expose
(
'/new/'
,
methods
=
(
'GET'
,
'POST'
))
def
create_view
(
self
):
...
...
flask_admin/model/fields.py
View file @
53c68c72
...
...
@@ -2,6 +2,7 @@ import itertools
from
wtforms.fields
import
FieldList
,
FormField
from
flask.ext.admin
import
_compat
from
.widgets
import
InlineFieldListWidget
,
InlineFormWidget
...
...
@@ -22,9 +23,9 @@ class InlineFieldList(FieldList):
def
__call__
(
self
,
**
kwargs
):
return
self
.
widget
(
self
,
template
=
self
.
template
,
check
=
self
.
display_row_controls
,
**
kwargs
)
template
=
self
.
template
,
check
=
self
.
display_row_controls
,
**
kwargs
)
def
display_row_controls
(
self
,
field
):
return
True
...
...
@@ -82,7 +83,7 @@ class InlineModelFormField(FormField):
return
getattr
(
self
.
form
,
self
.
_pk
)
.
data
def
populate_obj
(
self
,
obj
,
name
):
for
name
,
field
in
self
.
form
.
_fields
.
iteritems
(
):
for
name
,
field
in
_compat
.
iteritems
(
self
.
form
.
_fields
):
if
name
!=
self
.
_pk
:
field
.
populate_obj
(
obj
,
name
)
...
...
flask_admin/model/filters.py
View file @
53c68c72
from
flask.ext.admin
import
_compat
from
flask.ext.admin.babel
import
lazy_gettext
...
...
@@ -30,7 +31,7 @@ class BaseFilter(object):
Associated administrative view class.
"""
if
self
.
options
:
return
[(
v
,
unicode
(
n
))
for
v
,
n
in
self
.
options
]
return
[(
v
,
_compat
.
as_
unicode
(
n
))
for
v
,
n
in
self
.
options
]
return
None
...
...
flask_admin/model/form.py
View file @
53c68c72
import
inspect
from
flask.ext.admin.form
import
BaseForm
from
flask.ext.admin
import
_compat
def
converts
(
*
args
):
...
...
@@ -37,7 +38,7 @@ class InlineFormAdmin(object):
if
not
hasattr
(
self
,
k
):
setattr
(
self
,
k
,
None
)
for
k
,
v
in
kwargs
.
iteritems
(
):
for
k
,
v
in
_compat
.
iteritems
(
kwargs
):
setattr
(
self
,
k
,
v
)
def
postprocess_form
(
self
,
form_class
):
...
...
flask_admin/model/typefmt.py
View file @
53c68c72
from
jinja2
import
Markup
from
flask.ext.admin
import
_compat
def
null_formatter
(
view
,
value
):
...
...
@@ -38,7 +39,7 @@ def list_formatter(view, values):
:param values:
Value to check
"""
return
u', '
.
join
(
unicode
(
v
)
for
v
in
values
)
return
u', '
.
join
(
_compat
.
as_
unicode
(
v
)
for
v
in
values
)
BASE_FORMATTERS
=
{
...
...
flask_admin/static/js/form.js
View file @
53c68c72
...
...
@@ -22,7 +22,7 @@
this
.
addInlineField
=
function
(
id
,
el
,
template
)
{
var
$el
=
$
(
el
);
var
$template
=
$
(
template
);
var
$template
=
$
(
$
(
template
).
html
()
);
// Figure out new field ID
var
lastField
=
$el
.
children
(
'.fa-inline-field'
).
last
();
...
...
@@ -30,7 +30,7 @@
var
prefix
=
id
+
'-0'
;
if
(
lastField
.
length
>
0
)
{
var
parts
=
$
(
lastField
[
0
]).
attr
(
'id'
).
split
(
'-'
);
idx
=
parseInt
(
parts
[
parts
.
length
-
1
])
+
1
;
idx
=
parseInt
(
parts
[
parts
.
length
-
1
]
,
10
)
+
1
;
prefix
=
id
+
'-'
+
idx
;
}
...
...
flask_admin/templates/admin/model/inline_list_base.html
View file @
53c68c72
{% macro render_template(template, render) -%}
<div
class=
"fa-inline-field"
>
<div
class=
"fa-inline-field-control"
>
<a
href=
"javascript:void(0)"
class=
"fa-remove-field"
><i
class=
"icon-remove"
></i></a>
</div>
{{ render(template) }}
</div>
{%- endmacro %}
{% macro render_inline_fields(field, template, render, check=None) %}
<div
class=
"well"
>
<div
id=
"{{ field.id }}-fields"
>
...
...
@@ -23,6 +14,14 @@
</div>
{% endfor %}
</div>
<a
href=
"javascript:void(0)"
class=
"btn"
onclick=
"faForm.addInlineField('{{ field.id }}', '#{{ field.id }}-fields', {{ render_template(template, render)|tojson }});"
>
{{ _gettext('Add') }} {{ field.label.text }}
</a>
<div
id=
"{{ field.id }}-template"
class=
"hide"
>
<div
class=
"fa-inline-field"
>
<div
class=
"fa-inline-field-control"
>
<a
href=
"javascript:void(0)"
class=
"fa-remove-field"
><i
class=
"icon-remove"
></i></a>
</div>
{{ render(template) }}
</div>
</div>
<a
id=
"{{ field.id }}-button"
href=
"javascript:void(0)"
class=
"btn"
onclick=
"faForm.addInlineField('{{ field.id }}', '#{{ field.id }}-fields', '#{{ field.id }}-template');"
>
{{ _gettext('Add') }} {{ field.label.text }}
</a>
</div>
{% endmacro %}
flask_admin/tests/peeweemodel/test_basic.py
View file @
53c68c72
...
...
@@ -4,6 +4,7 @@ import peewee
from
wtforms
import
fields
from
flask.ext.admin
import
_compat
from
flask.ext.admin.contrib.peeweemodel
import
ModelView
from
.
import
setup
...
...
@@ -13,7 +14,7 @@ class CustomModelView(ModelView):
def
__init__
(
self
,
model
,
name
=
None
,
category
=
None
,
endpoint
=
None
,
url
=
None
,
**
kwargs
):
for
k
,
v
in
kwargs
.
iteritems
(
):
for
k
,
v
in
_compat
.
iteritems
(
kwargs
):
setattr
(
self
,
k
,
v
)
super
(
CustomModelView
,
self
)
.
__init__
(
model
,
...
...
flask_admin/tests/sqlamodel/test_basic.py
View file @
53c68c72
from
nose.tools
import
eq_
,
ok_
,
raises
from
wtforms
import
fields
from
flask.ext.admin
import
_compat
from
flask.ext.admin.contrib.sqlamodel
import
ModelView
from
.
import
setup
...
...
@@ -10,7 +12,7 @@ class CustomModelView(ModelView):
def
__init__
(
self
,
model
,
session
,
name
=
None
,
category
=
None
,
endpoint
=
None
,
url
=
None
,
**
kwargs
):
for
k
,
v
in
kwargs
.
iteritems
(
):
for
k
,
v
in
_compat
.
iteritems
(
kwargs
):
setattr
(
self
,
k
,
v
)
super
(
CustomModelView
,
self
)
.
__init__
(
model
,
session
,
...
...
flask_admin/tests/test_model.py
View file @
53c68c72
...
...
@@ -4,7 +4,7 @@ from flask import Flask
from
wtforms
import
fields
from
flask.ext.admin
import
Admin
,
form
from
flask.ext.admin
import
Admin
,
form
,
_compat
from
flask.ext.admin.model
import
base
,
filters
...
...
@@ -35,7 +35,7 @@ class MockModelView(base.BaseModelView):
def
__init__
(
self
,
model
,
name
=
None
,
category
=
None
,
endpoint
=
None
,
url
=
None
,
**
kwargs
):
# Allow to set any attributes from parameters
for
k
,
v
in
kwargs
.
iteritems
(
):
for
k
,
v
in
_compat
.
iteritems
(
kwargs
):
setattr
(
self
,
k
,
v
)
super
(
MockModelView
,
self
)
.
__init__
(
model
,
name
,
category
,
endpoint
,
url
)
...
...
flask_admin/tools.py
View file @
53c68c72
...
...
@@ -2,6 +2,9 @@ import sys
import
warnings
import
traceback
# Python 3 compatibility
from
._compat
import
reduce
def
import_module
(
name
,
required
=
True
):
"""
...
...
requirements.txt
View file @
53c68c72
six
Flask
>=0.7
Flask-SQLAlchemy
>=0.15
peewee
...
...
setup.py
View file @
53c68c72
...
...
@@ -42,7 +42,6 @@ setup(
zip_safe
=
False
,
platforms
=
'any'
,
install_requires
=
[
'six>=1.2'
,
'Flask>=0.7'
],
tests_require
=
[
...
...
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