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
cade92de
Commit
cade92de
authored
Aug 26, 2012
by
Serge S. Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added inline sqlalchemy model admin (WIP)
parent
e81c1312
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
465 additions
and
135 deletions
+465
-135
simple.py
examples/sqla/simple.py
+18
-1
fields.py
flask_admin/contrib/sqlamodel/fields.py
+79
-1
form.py
flask_admin/contrib/sqlamodel/form.py
+115
-45
tools.py
flask_admin/contrib/sqlamodel/tools.py
+15
-0
view.py
flask_admin/contrib/sqlamodel/view.py
+20
-9
__init__.py
flask_admin/model/__init__.py
+1
-0
form.py
flask_admin/model/form.py
+12
-0
widgets.py
flask_admin/model/widgets.py
+22
-0
filters.js
flask_admin/static/js/filters.js
+2
-2
form.js
flask_admin/static/js/form.js
+71
-23
lib.html
flask_admin/templates/admin/lib.html
+53
-39
create.html
flask_admin/templates/admin/model/create.html
+13
-9
edit.html
flask_admin/templates/admin/model/edit.html
+4
-1
inline_form.html
flask_admin/templates/admin/model/inline_form.html
+2
-0
inline_form_list.html
flask_admin/templates/admin/model/inline_form_list.html
+32
-0
list.html
flask_admin/templates/admin/model/list.html
+6
-5
No files found.
examples/sqla/simple.py
View file @
cade92de
...
@@ -28,6 +28,18 @@ class User(db.Model):
...
@@ -28,6 +28,18 @@ class User(db.Model):
return
self
.
username
return
self
.
username
class
UserInfo
(
db
.
Model
):
id
=
db
.
Column
(
db
.
Integer
,
primary_key
=
True
)
key
=
db
.
Column
(
db
.
String
(
64
))
value
=
db
.
Column
(
db
.
String
(
64
))
user_id
=
db
.
Column
(
db
.
Integer
(),
db
.
ForeignKey
(
User
.
id
))
user
=
db
.
relationship
(
User
,
backref
=
'info'
)
def
__unicode__
(
self
):
return
'
%
s -
%
s'
%
(
self
.
key
,
self
.
value
)
# Create M2M table
# Create M2M table
post_tags_table
=
db
.
Table
(
'post_tags'
,
db
.
Model
.
metadata
,
post_tags_table
=
db
.
Table
(
'post_tags'
,
db
.
Model
.
metadata
,
db
.
Column
(
'post_id'
,
db
.
Integer
,
db
.
ForeignKey
(
'post.id'
)),
db
.
Column
(
'post_id'
,
db
.
Integer
,
db
.
ForeignKey
(
'post.id'
)),
...
@@ -64,6 +76,11 @@ def index():
...
@@ -64,6 +76,11 @@ def index():
return
'<a href="/admin/">Click me to get to Admin!</a>'
return
'<a href="/admin/">Click me to get to Admin!</a>'
# Customized User model admin
class
UserAdmin
(
sqlamodel
.
ModelView
):
inline_models
=
(
'info'
,)
# Customized Post model admin
# Customized Post model admin
class
PostAdmin
(
sqlamodel
.
ModelView
):
class
PostAdmin
(
sqlamodel
.
ModelView
):
# Visible columns in the list view
# Visible columns in the list view
...
@@ -100,7 +117,7 @@ if __name__ == '__main__':
...
@@ -100,7 +117,7 @@ if __name__ == '__main__':
admin
=
admin
.
Admin
(
app
,
'Simple Models'
)
admin
=
admin
.
Admin
(
app
,
'Simple Models'
)
# Add views
# Add views
admin
.
add_view
(
sqlamodel
.
ModelView
(
User
,
db
.
session
))
admin
.
add_view
(
UserAdmin
(
User
,
db
.
session
))
admin
.
add_view
(
sqlamodel
.
ModelView
(
Tag
,
db
.
session
))
admin
.
add_view
(
sqlamodel
.
ModelView
(
Tag
,
db
.
session
))
admin
.
add_view
(
PostAdmin
(
db
.
session
))
admin
.
add_view
(
PostAdmin
(
db
.
session
))
...
...
flask_admin/contrib/sqlamodel/fields.py
View file @
cade92de
...
@@ -4,9 +4,14 @@
...
@@ -4,9 +4,14 @@
import
operator
import
operator
from
wtforms
import
widgets
from
wtforms
import
widgets
from
wtforms.fields
import
SelectFieldBase
from
wtforms.fields
import
SelectFieldBase
,
FormField
,
FieldList
from
wtforms.validators
import
ValidationError
from
wtforms.validators
import
ValidationError
from
.tools
import
get_primary_key
from
flask.ext.admin.model.widgets
import
InlineFormListWidget
from
flask
import
request
try
:
try
:
from
sqlalchemy.orm.util
import
identity_key
from
sqlalchemy.orm.util
import
identity_key
has_identity_key
=
True
has_identity_key
=
True
...
@@ -176,6 +181,79 @@ class QuerySelectMultipleField(QuerySelectField):
...
@@ -176,6 +181,79 @@ class QuerySelectMultipleField(QuerySelectField):
raise
ValidationError
(
self
.
gettext
(
'Not a valid choice'
))
raise
ValidationError
(
self
.
gettext
(
'Not a valid choice'
))
class
InlineModelFormField
(
FormField
):
def
__init__
(
self
,
form
,
model
,
**
kwargs
):
super
(
InlineModelFormField
,
self
)
.
__init__
(
form
,
**
kwargs
)
self
.
model
=
model
self
.
_pk
=
get_primary_key
(
model
)
self
.
_should_delete
=
False
def
process
(
self
,
formdata
,
data
=
None
):
super
(
InlineModelFormField
,
self
)
.
process
(
formdata
,
data
)
# Grab delete key
key
=
'del-
%
s'
%
self
.
id
if
key
in
request
.
form
:
self
.
_should_delete
=
True
def
should_delete
(
self
):
return
self
.
_should_delete
def
get_pk
(
self
):
return
getattr
(
self
.
form
,
self
.
_pk
)
.
data
def
populate_obj
(
self
,
obj
,
name
):
for
name
,
field
in
self
.
form
.
_fields
.
iteritems
():
if
name
!=
self
.
_pk
:
field
.
populate_obj
(
obj
,
name
)
class
InlineModelFormList
(
FieldList
):
widget
=
InlineFormListWidget
()
def
__init__
(
self
,
form
,
session
,
model
,
**
kwargs
):
self
.
form
=
form
self
.
session
=
session
self
.
model
=
model
self
.
_pk
=
get_primary_key
(
model
)
super
(
InlineModelFormList
,
self
)
.
__init__
(
InlineModelFormField
(
form
,
model
),
**
kwargs
)
def
__call__
(
self
,
**
kwargs
):
return
self
.
widget
(
self
,
template
=
self
.
form
(),
**
kwargs
)
def
populate_obj
(
self
,
obj
,
name
):
values
=
getattr
(
obj
,
name
,
None
)
if
values
is
None
:
return
# Create primary key map
pk_map
=
dict
((
str
(
getattr
(
v
,
self
.
_pk
)),
v
)
for
v
in
values
)
# Create fake object to work around wtforms limitations
for
field
in
self
.
entries
:
field_id
=
field
.
get_pk
()
if
field_id
in
pk_map
:
model
=
pk_map
[
field_id
]
if
field
.
should_delete
():
self
.
session
.
delete
(
model
)
continue
else
:
model
=
self
.
model
()
values
.
append
(
model
)
field
.
populate_obj
(
model
,
None
)
# Force relation
model
.
user
=
obj
def
get_pk_from_identity
(
obj
):
def
get_pk_from_identity
(
obj
):
cls
,
key
=
identity_key
(
instance
=
obj
)
cls
,
key
=
identity_key
(
instance
=
obj
)
return
u':'
.
join
(
unicode
(
x
)
for
x
in
key
)
return
u':'
.
join
(
unicode
(
x
)
for
x
in
key
)
flask_admin/contrib/sqlamodel/form.py
View file @
cade92de
from
wtforms
import
fields
,
validators
from
wtforms
import
fields
,
validators
from
flask.ext.admin
import
form
from
flask.ext.admin
import
form
from
flask.ext.admin.model.form
import
converts
,
ModelConverterBase
from
flask.ext.admin.model.form
import
converts
,
ModelConverterBase
,
InlineFormAdmin
from
.validators
import
Unique
from
.validators
import
Unique
from
.fields
import
QuerySelectField
,
QuerySelectMultipleField
from
.fields
import
QuerySelectField
,
QuerySelectMultipleField
,
InlineModelFormList
class
AdminModelConverter
(
ModelConverterBase
):
class
AdminModelConverter
(
ModelConverterBase
):
"""
"""
SQLAlchemy model to form converter
SQLAlchemy model to form converter
"""
"""
def
__init__
(
self
,
view
):
def
__init__
(
self
,
session
,
view
):
super
(
AdminModelConverter
,
self
)
.
__init__
()
super
(
AdminModelConverter
,
self
)
.
__init__
()
self
.
session
=
session
self
.
view
=
view
self
.
view
=
view
def
_get_label
(
self
,
name
,
field_args
):
def
_get_label
(
self
,
name
,
field_args
):
if
'label'
in
field_args
:
if
'label'
in
field_args
:
return
field_args
[
'label'
]
return
field_args
[
'label'
]
if
self
.
view
.
rename_columns
:
rename_columns
=
getattr
(
self
.
view
,
'rename_columns'
,
None
)
return
self
.
view
.
rename_columns
.
get
(
name
)
if
rename_columns
:
return
rename_columns
.
get
(
name
)
return
None
return
None
def
_get_field_override
(
self
,
name
):
def
_get_field_override
(
self
,
name
):
if
self
.
view
.
form_overrides
:
form_overrides
=
getattr
(
self
.
view
,
'form_overrides'
,
None
)
return
self
.
view
.
form_overrides
.
get
(
name
)
if
form_overrides
:
return
form_overrides
.
get
(
name
)
return
None
return
None
def
convert
(
self
,
model
,
mapper
,
prop
,
field_args
):
def
convert
(
self
,
model
,
mapper
,
prop
,
field_args
,
hidden_pk
):
kwargs
=
{
kwargs
=
{
'validators'
:
[],
'validators'
:
[],
'filters'
:
[]
'filters'
:
[]
...
@@ -48,7 +53,7 @@ class AdminModelConverter(ModelConverterBase):
...
@@ -48,7 +53,7 @@ class AdminModelConverter(ModelConverterBase):
kwargs
.
update
({
kwargs
.
update
({
'allow_blank'
:
local_column
.
nullable
,
'allow_blank'
:
local_column
.
nullable
,
'label'
:
self
.
_get_label
(
prop
.
key
,
kwargs
),
'label'
:
self
.
_get_label
(
prop
.
key
,
kwargs
),
'query_factory'
:
lambda
:
self
.
view
.
session
.
query
(
remote_model
)
'query_factory'
:
lambda
:
self
.
session
.
query
(
remote_model
)
})
})
if
local_column
.
nullable
:
if
local_column
.
nullable
:
...
@@ -66,7 +71,7 @@ class AdminModelConverter(ModelConverterBase):
...
@@ -66,7 +71,7 @@ class AdminModelConverter(ModelConverterBase):
**
kwargs
)
**
kwargs
)
elif
prop
.
direction
.
name
==
'ONETOMANY'
:
elif
prop
.
direction
.
name
==
'ONETOMANY'
:
# Skip backrefs
# Skip backrefs
if
not
local_column
.
foreign_keys
and
self
.
view
.
hide_backrefs
:
if
not
local_column
.
foreign_keys
and
getattr
(
self
.
view
,
'hide_backrefs'
,
False
)
:
return
None
return
None
return
QuerySelectMultipleField
(
return
QuerySelectMultipleField
(
...
@@ -93,22 +98,28 @@ class AdminModelConverter(ModelConverterBase):
...
@@ -93,22 +98,28 @@ class AdminModelConverter(ModelConverterBase):
unique
=
False
unique
=
False
if
column
.
primary_key
:
if
column
.
primary_key
:
if
hidden_pk
:
# If requested to add hidden field, show it
return
fields
.
HiddenField
()
else
:
# By default, don't show primary keys either
# By default, don't show primary keys either
if
self
.
view
.
form_columns
is
None
:
form_columns
=
getattr
(
self
.
view
,
'form_columns'
,
None
)
if
form_columns
is
None
:
return
None
return
None
# If PK is not explicitly allowed, ignore it
# If PK is not explicitly allowed, ignore it
if
prop
.
key
not
in
self
.
view
.
form_columns
:
if
prop
.
key
not
in
form_columns
:
return
None
return
None
kwargs
[
'validators'
]
.
append
(
Unique
(
self
.
view
.
session
,
kwargs
[
'validators'
]
.
append
(
Unique
(
self
.
session
,
model
,
model
,
column
))
column
))
unique
=
True
unique
=
True
# If field is unique, validate it
# If field is unique, validate it
if
column
.
unique
and
not
unique
:
if
column
.
unique
and
not
unique
:
kwargs
[
'validators'
]
.
append
(
Unique
(
self
.
view
.
session
,
kwargs
[
'validators'
]
.
append
(
Unique
(
self
.
session
,
model
,
model
,
column
))
column
))
...
@@ -221,10 +232,14 @@ class AdminModelConverter(ModelConverterBase):
...
@@ -221,10 +232,14 @@ class AdminModelConverter(ModelConverterBase):
field_args
[
'validators'
]
.
append
(
validators
.
UUID
())
field_args
[
'validators'
]
.
append
(
validators
.
UUID
())
return
fields
.
TextField
(
**
field_args
)
return
fields
.
TextField
(
**
field_args
)
# Get list of fields and generate form
def
get_form
(
self
,
model
,
base_class
=
form
.
BaseForm
,
# Get list of fields and generate form
def
get_form
(
model
,
converter
,
base_class
=
form
.
BaseForm
,
only
=
None
,
exclude
=
None
,
only
=
None
,
exclude
=
None
,
field_args
=
None
):
field_args
=
None
,
hidden_pk
=
False
):
# TODO: Support new 0.8 API
# TODO: Support new 0.8 API
if
not
hasattr
(
model
,
'_sa_class_manager'
):
if
not
hasattr
(
model
,
'_sa_class_manager'
):
raise
TypeError
(
'model must be a sqlalchemy mapped model'
)
raise
TypeError
(
'model must be a sqlalchemy mapped model'
)
...
@@ -240,8 +255,63 @@ class AdminModelConverter(ModelConverterBase):
...
@@ -240,8 +255,63 @@ class AdminModelConverter(ModelConverterBase):
field_dict
=
{}
field_dict
=
{}
for
name
,
prop
in
properties
:
for
name
,
prop
in
properties
:
field
=
self
.
convert
(
model
,
mapper
,
prop
,
field_args
.
get
(
name
)
)
field
=
converter
.
convert
(
model
,
mapper
,
prop
,
field_args
.
get
(
name
),
hidden_pk
)
if
field
is
not
None
:
if
field
is
not
None
:
field_dict
[
name
]
=
field
field_dict
[
name
]
=
field
return
type
(
model
.
__name__
+
'Form'
,
(
base_class
,
),
field_dict
)
return
type
(
model
.
__name__
+
'Form'
,
(
base_class
,
),
field_dict
)
def
contribute_inline
(
session
,
model
,
form_class
,
inline_models
):
# Get mapper
mapper
=
model
.
_sa_class_manager
.
mapper
# Contribute columns
for
p
in
inline_models
:
# Figure out
if
isinstance
(
p
,
basestring
):
info
=
InlineFormAdmin
(
p
)
elif
isinstance
(
p
,
tuple
):
info
=
InlineFormAdmin
(
p
[
0
],
**
p
[
1
])
elif
isinstance
(
p
,
InlineFormAdmin
):
info
=
p
else
:
raise
Exception
(
'Unknown inline model admin:
%
s'
%
repr
(
p
))
prop
=
mapper
.
get_property
(
info
.
field
)
if
prop
is
None
:
raise
Exception
(
'Inline form property
%
s.
%
s was not found'
%
(
model
.
__name__
,
info
.
field
))
if
not
hasattr
(
prop
,
'direction'
):
raise
Exception
(
'Failed to convert inline admin
%
s - only one-to-many relations are supported'
%
info
.
field
)
if
prop
.
direction
.
name
!=
'ONETOMANY'
:
raise
Exception
(
'Failed to convert inline admin
%
s - only one-to-many relations are supported'
%
info
.
field
)
# Find reverse relationship (to exlude from the list)
ignore
=
[]
for
remote_prop
in
prop
.
mapper
.
iterate_properties
:
if
hasattr
(
remote_prop
,
'direction'
)
and
remote_prop
.
direction
.
name
==
'MANYTOONE'
:
if
remote_prop
.
mapper
.
class_
==
prop
.
parent
.
class_
:
ignore
.
append
(
remote_prop
.
key
)
print
remote_prop
.
key
if
info
.
exclude
:
exclude
=
ignore
+
info
.
exclude
else
:
exclude
=
ignore
# Create field
remote_model
=
prop
.
mapper
.
class_
converter
=
AdminModelConverter
(
session
,
info
)
child_form
=
get_form
(
remote_model
,
converter
,
only
=
info
.
include
,
exclude
=
exclude
,
hidden_pk
=
True
)
setattr
(
form_class
,
p
,
InlineModelFormList
(
child_form
,
session
,
remote_model
))
return
form_class
flask_admin/contrib/sqlamodel/tools.py
View file @
cade92de
...
@@ -7,3 +7,18 @@ def parse_like_term(term):
...
@@ -7,3 +7,18 @@ def parse_like_term(term):
stmt
=
'
%%%
s
%%
'
%
term
stmt
=
'
%%%
s
%%
'
%
term
return
stmt
return
stmt
def
get_primary_key
(
model
):
"""
Return primary key name from a model
"""
props
=
model
.
_sa_class_manager
.
mapper
.
iterate_properties
for
p
in
props
:
if
hasattr
(
p
,
'columns'
):
for
c
in
p
.
columns
:
if
c
.
primary_key
:
return
p
.
key
return
None
flask_admin/contrib/sqlamodel/view.py
View file @
cade92de
...
@@ -124,6 +124,17 @@ class ModelView(BaseModelView):
...
@@ -124,6 +124,17 @@ class ModelView(BaseModelView):
for your model.
for your model.
"""
"""
inline_models
=
None
"""
Inline related-model editing for parent to child relation.
If you have child relation with name 'posts', you can generate inline
administration interface by using this code::
class MyModelView(BaseModelView):
inline_models = ('posts',)
"""
def
__init__
(
self
,
model
,
session
,
def
__init__
(
self
,
model
,
session
,
name
=
None
,
category
=
None
,
endpoint
=
None
,
url
=
None
):
name
=
None
,
category
=
None
,
endpoint
=
None
,
url
=
None
):
"""
"""
...
@@ -178,13 +189,7 @@ class ModelView(BaseModelView):
...
@@ -178,13 +189,7 @@ class ModelView(BaseModelView):
"""
"""
Return primary key name from a model
Return primary key name from a model
"""
"""
for
p
in
self
.
_get_model_iterator
():
return
tools
.
get_primary_key
(
self
.
model
)
if
hasattr
(
p
,
'columns'
):
for
c
in
p
.
columns
:
if
c
.
primary_key
:
return
p
.
key
return
None
def
get_pk_value
(
self
,
model
):
def
get_pk_value
(
self
,
model
):
"""
"""
...
@@ -370,12 +375,18 @@ class ModelView(BaseModelView):
...
@@ -370,12 +375,18 @@ class ModelView(BaseModelView):
"""
"""
Create form from the model.
Create form from the model.
"""
"""
converter
=
form
.
AdminModelConverter
(
self
)
converter
=
form
.
AdminModelConverter
(
self
.
session
,
self
)
return
converter
.
get_form
(
self
.
model
,
form_class
=
form
.
get_form
(
self
.
model
,
converter
,
only
=
self
.
form_columns
,
only
=
self
.
form_columns
,
exclude
=
self
.
excluded_form_columns
,
exclude
=
self
.
excluded_form_columns
,
field_args
=
self
.
form_args
)
field_args
=
self
.
form_args
)
if
self
.
inline_models
:
form_class
=
form
.
contribute_inline
(
self
.
session
,
self
.
model
,
form_class
,
self
.
inline_models
)
return
form_class
def
scaffold_auto_joins
(
self
):
def
scaffold_auto_joins
(
self
):
"""
"""
Return list of joined tables by going through the
Return list of joined tables by going through the
...
...
flask_admin/model/__init__.py
View file @
cade92de
from
.base
import
BaseModelView
from
.base
import
BaseModelView
from
.form
import
InlineFormAdmin
from
flask.ext.admin.actions
import
action
from
flask.ext.admin.actions
import
action
flask_admin/model/form.py
View file @
cade92de
...
@@ -10,6 +10,18 @@ def converts(*args):
...
@@ -10,6 +10,18 @@ def converts(*args):
return
_inner
return
_inner
class
InlineFormAdmin
(
object
):
def
__init__
(
self
,
field
,
**
kwargs
):
self
.
field
=
field
defaults
=
dict
(
include
=
None
,
exclude
=
None
)
defaults
.
update
(
kwargs
)
for
k
,
v
in
defaults
.
iteritems
():
setattr
(
self
,
k
,
v
)
class
ModelConverterBase
(
object
):
class
ModelConverterBase
(
object
):
def
__init__
(
self
,
converters
=
None
,
use_mro
=
True
):
def
__init__
(
self
,
converters
=
None
,
use_mro
=
True
):
self
.
use_mro
=
use_mro
self
.
use_mro
=
use_mro
...
...
flask_admin/model/widgets.py
0 → 100644
View file @
cade92de
from
flask.globals
import
_request_ctx_stack
class
RenderTemplateWidget
(
object
):
def
__init__
(
self
,
template
):
self
.
template
=
template
def
__call__
(
self
,
field
,
**
kwargs
):
ctx
=
_request_ctx_stack
.
top
jinja_env
=
ctx
.
app
.
jinja_env
print
kwargs
kwargs
[
'field'
]
=
field
template
=
jinja_env
.
get_template
(
self
.
template
)
return
template
.
render
(
kwargs
)
class
InlineFormListWidget
(
RenderTemplateWidget
):
def
__init__
(
self
):
super
(
InlineFormListWidget
,
self
)
.
__init__
(
'admin/model/inline_form_list.html'
)
flask_admin/static/js/filters.js
View file @
cade92de
var
AdminFilters
=
function
(
element
,
filters_element
,
adminForm
,
operations
,
options
,
types
)
{
var
AdminFilters
=
function
(
element
,
filters_element
,
operations
,
options
,
types
)
{
var
$root
=
$
(
element
);
var
$root
=
$
(
element
);
var
$container
=
$
(
'.filters'
,
$root
);
var
$container
=
$
(
'.filters'
,
$root
);
var
lastCount
=
0
;
var
lastCount
=
0
;
...
@@ -68,7 +68,7 @@ var AdminFilters = function(element, filters_element, adminForm, operations, opt
...
@@ -68,7 +68,7 @@ var AdminFilters = function(element, filters_element, adminForm, operations, opt
if
(
optId
in
types
)
{
if
(
optId
in
types
)
{
$field
.
attr
(
'data-role'
,
types
[
optId
]);
$field
.
attr
(
'data-role'
,
types
[
optId
]);
admin
Form
.
applyStyle
(
$field
,
types
[
optId
]);
fa
Form
.
applyStyle
(
$field
,
types
[
optId
]);
}
}
lastCount
+=
1
;
lastCount
+=
1
;
...
...
flask_admin/static/js/form.js
View file @
cade92de
var
AdminForm
=
function
()
{
(
function
()
{
var
AdminForm
=
function
()
{
this
.
applyStyle
=
function
(
el
,
name
)
{
this
.
applyStyle
=
function
(
el
,
name
)
{
switch
(
name
)
{
switch
(
name
)
{
case
'chosen'
:
case
'chosen'
:
...
@@ -13,12 +14,59 @@ var AdminForm = function() {
...
@@ -13,12 +14,59 @@ var AdminForm = function() {
case
'datetimepicker'
:
case
'datetimepicker'
:
$
(
el
).
datepicker
({
displayTime
:
true
});
$
(
el
).
datepicker
({
displayTime
:
true
});
break
;
break
;
}
};
};
this
.
addInlineModel
=
function
(
id
,
el
,
template
)
{
var
$el
=
$
(
el
);
var
$template
=
$
(
template
);
// Figure out new form ID
var
lastForm
=
$el
.
children
(
'.fa-inline-form'
).
last
();
var
prefix
=
id
+
'-0'
;
if
(
lastForm
.
length
>
0
)
{
var
parts
=
$
(
lastForm
[
0
]).
attr
(
'id'
).
split
(
'-'
);
idx
=
parseInt
(
parts
[
parts
.
length
-
1
])
+
1
;
prefix
=
id
+
'-'
+
idx
;
}
}
};
// Apply automatic styles
// Set form ID
$
(
'[data-role=chosen]'
).
chosen
();
$template
.
attr
(
'id'
,
prefix
);
$
(
'[data-role=chosenblank]'
).
chosen
({
allow_single_deselect
:
true
});
$
(
'[data-role=datepicker]'
).
datepicker
();
// Fix form IDs
$
(
'[data-role=datetimepicker]'
).
datepicker
({
displayTime
:
true
});
$
(
'[name]'
,
$template
).
each
(
function
(
e
)
{
var
me
=
$
(
this
);
me
.
attr
(
'id'
,
prefix
+
'-'
+
me
.
attr
(
'id'
));
me
.
attr
(
'name'
,
prefix
+
'-'
+
me
.
attr
(
'name'
));
});
$template
.
appendTo
(
$el
);
// Apply styles
this
.
applyGlobalStyles
(
$template
);
};
this
.
applyGlobalStyles
=
function
(
parent
)
{
$
(
'[data-role=chosen]'
,
parent
).
chosen
();
$
(
'[data-role=chosenblank]'
,
parent
).
chosen
({
allow_single_deselect
:
true
});
$
(
'[data-role=datepicker]'
,
parent
).
datepicker
();
$
(
'[data-role=datetimepicker]'
,
parent
).
datepicker
({
displayTime
:
true
});
};
};
// Add live event handler
$
(
'.fa-remove-form'
).
live
(
'click'
,
function
(
e
)
{
e
.
preventDefault
();
var
form
=
$
(
this
).
closest
(
'.fa-inline-form'
);
form
.
remove
();
});
// Expose faForm globally
var
faForm
=
window
.
faForm
=
new
AdminForm
();
// Apply global styles
faForm
.
applyGlobalStyles
(
document
);
})();
flask_admin/templates/admin/lib.html
View file @
cade92de
...
@@ -73,21 +73,19 @@
...
@@ -73,21 +73,19 @@
{% endif %}
{% endif %}
{%- endmacro %}
{%- endmacro %}
{% macro render_form(form, cancel_url, extra=None) -%}
{% macro render_form_fields(form, focus_set=False) %}
<form
action=
""
method=
"POST"
class=
"form-horizontal"
{%
if
form
.
has_file_field
%}
enctype=
"multipart/form-data"
{%
endif
%}
>
<fieldset>
{{ form.hidden_tag() }}
{{ form.hidden_tag() }}
{% for f in form if f.name != 'csrf_token' and f.name != 'csrf
' %}
{% for f in form if f.type != 'HiddenField' and f.type != 'CSRFTokenField
' %}
<div
class=
"control-group{% if f.errors %} error{% endif %}"
>
<div
class=
"control-group{% if f.errors %} error{% endif %}"
>
{{ f.label(class='control-label') }}
{{ f.label(class='control-label') }}
<div
class=
"controls"
>
<div
class=
"controls"
>
<div>
<div>
{% if not focus_set %}
{% if not focus_set %}
{{ f(autofocus='autofocus')
}}
{{ f(autofocus='autofocus')|safe
}}
{% set focus_set = True %}
{% set focus_set = True %}
{% else %}
{% else %}
{{ f()
}}
{{ f()|safe
}}
{% endif %}
{% endif %}
</div>
</div>
{% if f.description %}
{% if f.description %}
...
@@ -103,6 +101,17 @@
...
@@ -103,6 +101,17 @@
</div>
</div>
</div>
</div>
{% endfor %}
{% endfor %}
{% endmacro %}
{% macro form_tag() %}
<form
action=
""
method=
"POST"
class=
"form-horizontal"
{%
if
form
.
has_file_field
%}
enctype=
"multipart/form-data"
{%
endif
%}
>
<fieldset>
{{ caller() }}
</fieldset>
</form>
{% endmacro %}
{% macro render_form_buttons(cancel_url, extra=None) %}
<div
class=
"control-group"
>
<div
class=
"control-group"
>
<div
class=
"controls"
>
<div
class=
"controls"
>
<input
type=
"submit"
class=
"btn btn-primary btn-large"
value=
"{{ _gettext('Submit') }}"
/>
<input
type=
"submit"
class=
"btn btn-primary btn-large"
value=
"{{ _gettext('Submit') }}"
/>
...
@@ -114,7 +123,12 @@
...
@@ -114,7 +123,12 @@
{% endif %}
{% endif %}
</div>
</div>
</div>
</div>
</fieldset>
{% endmacro %}
</form>
{% macro render_form(form, cancel_url, extra=None) -%}
{% call form_tag() %}
{{ render_form_fields(form) }}
{{ render_form_buttons(cancel_url, extra) }}
{% endcall %}
{% endmacro %}
{% endmacro %}
flask_admin/templates/admin/model/create.html
View file @
cade92de
...
@@ -7,10 +7,6 @@
...
@@ -7,10 +7,6 @@
{% endblock %}
{% endblock %}
{% block body %}
{% block body %}
{% macro extra() %}
<input
name=
"_add_another"
type=
"submit"
class=
"btn btn-large"
value=
"{{ _gettext('Save and Add') }}"
/>
{% endmacro %}
<ul
class=
"nav nav-tabs"
>
<ul
class=
"nav nav-tabs"
>
<li>
<li>
<a
href=
"{{ return_url }}"
>
{{ _gettext('List') }}
</a>
<a
href=
"{{ return_url }}"
>
{{ _gettext('List') }}
</a>
...
@@ -19,7 +15,15 @@
...
@@ -19,7 +15,15 @@
<a
href=
"#"
>
{{ _gettext('Create') }}
</a>
<a
href=
"#"
>
{{ _gettext('Create') }}
</a>
</li>
</li>
</ul>
</ul>
{{ lib.render_form(form, return_url, extra()) }}
{% macro extra() %}
<input
name=
"_add_another"
type=
"submit"
class=
"btn btn-large"
value=
"{{ _gettext('Save and Add') }}"
/>
{% endmacro %}
{% call lib.form_tag() %}
{{ lib.render_form_fields(form) }}
{{ lib.render_form_buttons(cancel_url, extra()) }}
{% endcall %}
{% endblock %}
{% endblock %}
{% block tail %}
{% block tail %}
...
...
flask_admin/templates/admin/model/edit.html
View file @
cade92de
...
@@ -7,7 +7,10 @@
...
@@ -7,7 +7,10 @@
{% endblock %}
{% endblock %}
{% block body %}
{% block body %}
{{ lib.render_form(form, return_url) }}
{% call lib.form_tag() %}
{{ lib.render_form_fields(form) }}
{{ lib.render_form_buttons(cancel_url) }}
{% endcall %}
{% endblock %}
{% endblock %}
{% block tail %}
{% block tail %}
...
...
flask_admin/templates/admin/model/inline_form.html
0 → 100644
View file @
cade92de
{% import 'admin/lib.html' as lib with context %}
flask_admin/templates/admin/model/inline_form_list.html
0 → 100644
View file @
cade92de
{% import 'admin/lib.html' as lib with context %}
{% macro render_form(form) %}
{% endmacro %}
{% macro render_template(template) -%}
<div
class=
"fa-inline-form"
>
<div
style=
"float: right"
>
<a
href=
"#"
class=
"fa-remove-form"
>
x
</a>
</div>
{{ lib.render_form_fields(template) }}
<hr/>
</div>
{%- endmacro %}
<div
class=
"well"
>
<div
id=
"{{ field.id }}-forms"
>
{% for subfield in field %}
<div
id=
"{{ subfield.id }}"
class=
"fa-inline-form"
>
{% set pk = subfield.get_pk() %}
{%- if pk %}
<div
style=
"float: right"
>
<input
type=
"checkbox"
name=
"del-{{ subfield.id }}"
id=
"del-{{ subfield.id }}"
/>
Delete?
</div>
{%- endif -%}
{{ lib.render_form_fields(subfield, True) }}
<hr/>
</div>
{% endfor %}
</div>
<a
href=
"#"
class=
"btn"
onclick=
"faForm.addInlineModel('{{ field.id }}', '#{{ field.id }}-forms', {{ render_template(template)|tojson }});"
>
Add {{ field.name }}
</a>
</div>
flask_admin/templates/admin/model/list.html
View file @
cade92de
...
@@ -174,11 +174,12 @@
...
@@ -174,11 +174,12 @@
{% if filter_groups is not none and filter_data is not none %}
{% if filter_groups is not none and filter_data is not none %}
<script
language=
"javascript"
>
<script
language=
"javascript"
>
var
form
=
new
AdminForm
();
(
function
()
{
var
filter
=
new
AdminFilters
(
'#filter_form'
,
'.field-filters'
,
form
,
var
filter
=
new
AdminFilters
(
'#filter_form'
,
'.field-filters'
,
{{
admin_view
.
_filter_dict
|
tojson
|
safe
}},
{{
admin_view
.
_filter_dict
|
tojson
|
safe
}},
{{
filter_data
|
tojson
|
safe
}},
{{
filter_data
|
tojson
|
safe
}},
{{
filter_types
|
tojson
|
safe
}});
{{
filter_types
|
tojson
|
safe
}});
})();
</script>
</script>
{% endif %}
{% endif %}
{% endblock %}
{% endblock %}
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