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
d2b6f20a
Commit
d2b6f20a
authored
Aug 25, 2013
by
Florian Sachs
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'upstream/master'
parents
57ff13b7
79f4f907
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
71 additions
and
41 deletions
+71
-41
db_sqla.rst
doc/db_sqla.rst
+7
-8
__init__.py
flask_admin/contrib/mongoengine/__init__.py
+1
-0
form.py
flask_admin/contrib/mongoengine/form.py
+9
-7
view.py
flask_admin/contrib/mongoengine/view.py
+5
-6
form.py
flask_admin/contrib/sqla/form.py
+5
-5
upload.py
flask_admin/form/upload.py
+14
-5
fields.py
flask_admin/model/fields.py
+20
-0
form.py
flask_admin/model/form.py
+6
-6
form.js
flask_admin/static/admin/js/form.js
+1
-1
inline_form.html
flask_admin/templates/admin/model/inline_form.html
+1
-1
test_basic.py
flask_admin/tests/mongoengine/test_basic.py
+2
-2
No files found.
doc/db_sqla.rst
View file @
d2b6f20a
...
@@ -106,10 +106,11 @@ configuration properties and methods.
...
@@ -106,10 +106,11 @@ configuration properties and methods.
Multiple Primary Keys
Multiple Primary Keys
---------------------
---------------------
Models with multiple primary keys have limited support, as a few pitfalls are waiting for you.
Flask-Admin has limited support for models with multiple primary keys. It only covers specific case when
With using multiple primary keys, weak entities can be used with Flask-Admin.
all but one primary keys are foreign keys to another model. For example, model inheritance following
this convention.
Lets Model a car with it
'
s tyres::
Lets Model a car with its tyres::
class Car(db.Model):
class Car(db.Model):
__tablename__ = 'cars'
__tablename__ = 'cars'
...
@@ -129,19 +130,17 @@ Lets Model a car with it's tyres::
...
@@ -129,19 +130,17 @@ Lets Model a car with it's tyres::
A specific tyre is identified by using the two primary key columns of the ``Tyre`` class, of which the ``car_id`` key
A specific tyre is identified by using the two primary key columns of the ``Tyre`` class, of which the ``car_id`` key
is itself a foreign key to the class ``Car``.
is itself a foreign key to the class ``Car``.
To be able to CRUD the ``Tyre`` class,
two steps are necessary, when defini
g the AdminView::
To be able to CRUD the ``Tyre`` class,
you need to enumerate columns when definin
g the AdminView::
class TyreAdmin(sqla.ModelView):
class TyreAdmin(sqla.ModelView):
form_columns = ['car', 'tyre_id', 'desc']
form_columns = ['car', 'tyre_id', 'desc']
The ``form_columns`` needs to be explizit, as per default only one primary key is displayed. When, like in this
The ``form_columns`` needs to be explicit, as per default only one primary key is displayed.
example, one part of the key is a foreign key, do not include the foreign-key-columns here, but the
corresponding relationship.
When having multiple primary keys, **no** validation for uniqueness *prior* to saving of the object will be done. Saving
When having multiple primary keys, **no** validation for uniqueness *prior* to saving of the object will be done. Saving
a model that violates a unique-constraint leads to an Sqlalchemy-Integrity-Error. In this case, ``Flask-Admin`` displays
a model that violates a unique-constraint leads to an Sqlalchemy-Integrity-Error. In this case, ``Flask-Admin`` displays
a proper error message and you can change the data in the form. When the application has been started with ``debug=True``
a proper error message and you can change the data in the form. When the application has been started with ``debug=True``
the ``werkzeug`` debugger
catches the exception and displays
the stacktrace.
the ``werkzeug`` debugger
will catch the exception and will display
the stacktrace.
A standalone script with the Examples from above can be found in the examples directory.
A standalone script with the Examples from above can be found in the examples directory.
...
...
flask_admin/contrib/mongoengine/__init__.py
View file @
d2b6f20a
...
@@ -4,3 +4,4 @@ except ImportError:
...
@@ -4,3 +4,4 @@ except ImportError:
raise
Exception
(
'Please install flask-mongoengine in order to use mongoengine backend'
)
raise
Exception
(
'Please install flask-mongoengine in order to use mongoengine backend'
)
from
.view
import
ModelView
from
.view
import
ModelView
from
.form
import
EmbeddedForm
flask_admin/contrib/mongoengine/form.py
View file @
d2b6f20a
...
@@ -7,7 +7,7 @@ from wtforms import fields, validators
...
@@ -7,7 +7,7 @@ from wtforms import fields, validators
from
flask.ext.mongoengine.wtf
import
orm
,
fields
as
mongo_fields
from
flask.ext.mongoengine.wtf
import
orm
,
fields
as
mongo_fields
from
flask.ext.admin
import
form
from
flask.ext.admin
import
form
from
flask.ext.admin.model.form
import
FieldPlaceholder
,
InlineFormAdmin
from
flask.ext.admin.model.form
import
FieldPlaceholder
,
Inline
Base
FormAdmin
from
flask.ext.admin.model.fields
import
InlineFieldList
from
flask.ext.admin.model.fields
import
InlineFieldList
from
flask.ext.admin.model.widgets
import
InlineFormWidget
from
flask.ext.admin.model.widgets
import
InlineFormWidget
from
flask.ext.admin._compat
import
iteritems
from
flask.ext.admin._compat
import
iteritems
...
@@ -15,6 +15,10 @@ from flask.ext.admin._compat import iteritems
...
@@ -15,6 +15,10 @@ from flask.ext.admin._compat import iteritems
from
.fields
import
ModelFormField
,
MongoFileField
,
MongoImageField
from
.fields
import
ModelFormField
,
MongoFileField
,
MongoImageField
class
EmbeddedForm
(
InlineBaseFormAdmin
):
pass
class
CustomModelConverter
(
orm
.
ModelConverter
):
class
CustomModelConverter
(
orm
.
ModelConverter
):
"""
"""
Customized MongoEngine form conversion class.
Customized MongoEngine form conversion class.
...
@@ -39,18 +43,16 @@ class CustomModelConverter(orm.ModelConverter):
...
@@ -39,18 +43,16 @@ class CustomModelConverter(orm.ModelConverter):
def
_get_subdocument_config
(
self
,
name
):
def
_get_subdocument_config
(
self
,
name
):
config
=
getattr
(
self
.
view
,
'form_subdocuments'
,
{})
config
=
getattr
(
self
.
view
,
'form_subdocuments'
,
{})
print
'x'
,
name
,
config
p
=
config
.
get
(
name
)
p
=
config
.
get
(
name
)
if
not
p
:
if
not
p
:
return
InlineFormAdmin
()
return
EmbeddedForm
()
if
isinstance
(
p
,
dict
):
if
isinstance
(
p
,
dict
):
return
InlineFormAdmin
(
**
p
)
return
EmbeddedForm
(
**
p
)
elif
isinstance
(
p
,
InlineFormAdmin
):
elif
isinstance
(
p
,
EmbeddedForm
):
return
p
return
p
raise
ValueError
(
'Invalid subdocument type: expecting dict or instance of
InlineFormAdmin
, got
%
s'
%
type
(
p
))
raise
ValueError
(
'Invalid subdocument type: expecting dict or instance of
flask.ext.admin.contrib.mongoengine.EmbeddedForm
, got
%
s'
%
type
(
p
))
def
clone_converter
(
self
,
view
):
def
clone_converter
(
self
,
view
):
return
self
.
__class__
(
view
)
return
self
.
__class__
(
view
)
...
...
flask_admin/contrib/mongoengine/view.py
View file @
d2b6f20a
...
@@ -9,7 +9,6 @@ from flask.ext.admin._compat import iteritems, string_types
...
@@ -9,7 +9,6 @@ from flask.ext.admin._compat import iteritems, string_types
import
mongoengine
import
mongoengine
import
gridfs
import
gridfs
from
mongoengine.fields
import
GridFSProxy
,
ImageGridFsProxy
from
mongoengine.connection
import
get_db
from
mongoengine.connection
import
get_db
from
bson.objectid
import
ObjectId
from
bson.objectid
import
ObjectId
...
@@ -98,12 +97,12 @@ class ModelView(BaseModelView):
...
@@ -98,12 +97,12 @@ class ModelView(BaseModelView):
List of allowed search field types.
List of allowed search field types.
"""
"""
form_subdocuments
=
None
form_subdocuments
=
{}
"""
"""
Subdocument configuration options.
Subdocument configuration options.
This field accepts dictionary, where key is field name and value is either dictionary or instance of the
This field accepts dictionary, where key is field name and value is either dictionary or instance of the
`
InlineFormAdmin
`.
`
flask.ext.admin.contrib.EmbeddedForm
`.
Consider following example::
Consider following example::
...
@@ -127,7 +126,7 @@ class ModelView(BaseModelView):
...
@@ -127,7 +126,7 @@ class ModelView(BaseModelView):
It is also possible to use class-based embedded document configuration:
It is also possible to use class-based embedded document configuration:
class CommentEmbed(
InlineFormAdmin
):
class CommentEmbed(
EmbeddedForm
):
form_columns = ('name',)
form_columns = ('name',)
class MyAdmin(ModelView):
class MyAdmin(ModelView):
...
@@ -137,10 +136,10 @@ class ModelView(BaseModelView):
...
@@ -137,10 +136,10 @@ class ModelView(BaseModelView):
Arbitrary depth nesting is supported::
Arbitrary depth nesting is supported::
class SomeEmbed(
InlineFormAdmin
):
class SomeEmbed(
EmbeddedForm
):
form_excluded_columns = ('test',)
form_excluded_columns = ('test',)
class CommentEmbed(
InlineFormAdmin
):
class CommentEmbed(
EmbeddedForm
):
form_columns = ('name',)
form_columns = ('name',)
form_subdocuments = {
form_subdocuments = {
'inner': SomeEmbed()
'inner': SomeEmbed()
...
...
flask_admin/contrib/sqla/form.py
View file @
d2b6f20a
...
@@ -4,7 +4,7 @@ from sqlalchemy import Boolean, Column
...
@@ -4,7 +4,7 @@ from sqlalchemy import Boolean, Column
from
flask.ext.admin
import
form
from
flask.ext.admin
import
form
from
flask.ext.admin.form
import
Select2Field
from
flask.ext.admin.form
import
Select2Field
from
flask.ext.admin.model.form
import
(
converts
,
ModelConverterBase
,
from
flask.ext.admin.model.form
import
(
converts
,
ModelConverterBase
,
Inline
Model
FormAdmin
,
InlineModelConverterBase
,
InlineFormAdmin
,
InlineModelConverterBase
,
FieldPlaceholder
)
FieldPlaceholder
)
from
flask.ext.admin.model.helpers
import
prettify_name
from
flask.ext.admin.model.helpers
import
prettify_name
from
flask.ext.admin._backwards
import
get_property
from
flask.ext.admin._backwards
import
get_property
...
@@ -439,7 +439,7 @@ class InlineModelConverter(InlineModelConverterBase):
...
@@ -439,7 +439,7 @@ class InlineModelConverter(InlineModelConverterBase):
Flask-Admin view object
Flask-Admin view object
:param model_converter:
:param model_converter:
Model converter class. Will be automatically instantiated with
Model converter class. Will be automatically instantiated with
appropriate `Inline
Model
FormAdmin` instance.
appropriate `InlineFormAdmin` instance.
"""
"""
super
(
InlineModelConverter
,
self
)
.
__init__
(
view
)
super
(
InlineModelConverter
,
self
)
.
__init__
(
view
)
self
.
session
=
session
self
.
session
=
session
...
@@ -451,7 +451,7 @@ class InlineModelConverter(InlineModelConverterBase):
...
@@ -451,7 +451,7 @@ class InlineModelConverter(InlineModelConverterBase):
# Special case for model instances
# Special case for model instances
if
info
is
None
:
if
info
is
None
:
if
hasattr
(
p
,
'_sa_class_manager'
):
if
hasattr
(
p
,
'_sa_class_manager'
):
return
Inline
Model
FormAdmin
(
p
)
return
InlineFormAdmin
(
p
)
else
:
else
:
model
=
getattr
(
p
,
'model'
,
None
)
model
=
getattr
(
p
,
'model'
,
None
)
...
@@ -463,9 +463,9 @@ class InlineModelConverter(InlineModelConverterBase):
...
@@ -463,9 +463,9 @@ class InlineModelConverter(InlineModelConverterBase):
if
not
attr
.
startswith
(
'_'
)
and
attr
!=
'model'
:
if
not
attr
.
startswith
(
'_'
)
and
attr
!=
'model'
:
attrs
[
attr
]
=
getattr
(
p
,
attr
)
attrs
[
attr
]
=
getattr
(
p
,
attr
)
return
Inline
Model
FormAdmin
(
model
,
**
attrs
)
return
InlineFormAdmin
(
model
,
**
attrs
)
info
=
Inline
Model
FormAdmin
(
model
,
**
attrs
)
info
=
InlineFormAdmin
(
model
,
**
attrs
)
return
info
return
info
...
...
flask_admin/form/upload.py
View file @
d2b6f20a
...
@@ -21,7 +21,6 @@ except ImportError:
...
@@ -21,7 +21,6 @@ except ImportError:
Image
=
None
Image
=
None
ImageOps
=
None
ImageOps
=
None
__all__
=
[
'FileUploadInput'
,
'FileUploadField'
,
__all__
=
[
'FileUploadInput'
,
'FileUploadField'
,
'ImageUploadInput'
,
'ImageUploadField'
,
'ImageUploadInput'
,
'ImageUploadField'
,
'namegen_filename'
,
'thumbgen_filename'
]
'namegen_filename'
,
'thumbgen_filename'
]
...
@@ -103,8 +102,6 @@ class ImageUploadInput(object):
...
@@ -103,8 +102,6 @@ class ImageUploadInput(object):
if
field
.
url_relative_path
:
if
field
.
url_relative_path
:
filename
=
urljoin
(
field
.
url_relative_path
,
filename
)
filename
=
urljoin
(
field
.
url_relative_path
,
filename
)
return
url_for
(
field
.
endpoint
,
filename
)
return
url_for
(
field
.
endpoint
,
filename
=
field
.
data
)
return
url_for
(
field
.
endpoint
,
filename
=
field
.
data
)
...
@@ -229,6 +226,9 @@ class FileUploadField(fields.TextField):
...
@@ -229,6 +226,9 @@ class FileUploadField(fields.TextField):
def
_save_file
(
self
,
data
,
filename
):
def
_save_file
(
self
,
data
,
filename
):
path
=
self
.
_get_path
(
filename
)
path
=
self
.
_get_path
(
filename
)
if
not
op
.
exists
(
op
.
dirname
(
path
)):
os
.
makedirs
(
os
.
path
.
dirname
(
path
),
0o666
)
data
.
save
(
path
)
data
.
save
(
path
)
return
filename
return
filename
...
@@ -328,6 +328,7 @@ class ImageUploadField(FileUploadField):
...
@@ -328,6 +328,7 @@ class ImageUploadField(FileUploadField):
self
.
thumbnail_size
=
thumbnail_size
self
.
thumbnail_size
=
thumbnail_size
self
.
endpoint
=
endpoint
self
.
endpoint
=
endpoint
self
.
image
=
None
self
.
image
=
None
self
.
url_relative_path
=
url_relative_path
if
not
allowed_extensions
:
if
not
allowed_extensions
:
allowed_extensions
=
(
'gif'
,
'jpg'
,
'jpeg'
,
'png'
,
'tiff'
)
allowed_extensions
=
(
'gif'
,
'jpg'
,
'jpeg'
,
'png'
,
'tiff'
)
...
@@ -362,6 +363,10 @@ class ImageUploadField(FileUploadField):
...
@@ -362,6 +363,10 @@ class ImageUploadField(FileUploadField):
# Saving
# Saving
def
_save_file
(
self
,
data
,
filename
):
def
_save_file
(
self
,
data
,
filename
):
path
=
self
.
_get_path
(
filename
)
if
not
op
.
exists
(
op
.
dirname
(
path
)):
os
.
makedirs
(
os
.
path
.
dirname
(
path
),
0o666
)
if
self
.
image
and
self
.
max_size
:
if
self
.
image
and
self
.
max_size
:
filename
,
format
=
self
.
_get_save_format
(
filename
,
self
.
image
)
filename
,
format
=
self
.
_get_save_format
(
filename
,
self
.
image
)
...
@@ -369,7 +374,8 @@ class ImageUploadField(FileUploadField):
...
@@ -369,7 +374,8 @@ class ImageUploadField(FileUploadField):
self
.
_get_path
(
filename
),
self
.
_get_path
(
filename
),
format
)
format
)
else
:
else
:
data
.
save
(
self
.
_get_path
(
filename
))
data
.
seek
(
0
)
data
.
save
(
path
)
self
.
_save_thumbnail
(
data
,
filename
)
self
.
_save_thumbnail
(
data
,
filename
)
...
@@ -389,11 +395,14 @@ class ImageUploadField(FileUploadField):
...
@@ -389,11 +395,14 @@ class ImageUploadField(FileUploadField):
if
force
:
if
force
:
return
ImageOps
.
fit
(
self
.
image
,
(
width
,
height
),
Image
.
ANTIALIAS
)
return
ImageOps
.
fit
(
self
.
image
,
(
width
,
height
),
Image
.
ANTIALIAS
)
else
:
else
:
return
self
.
image
.
copy
()
.
thumbnail
((
width
,
height
),
Image
.
ANTIALIAS
)
thumb
=
self
.
image
.
copy
()
thumb
.
thumbnail
((
width
,
height
),
Image
.
ANTIALIAS
)
return
thumb
return
image
return
image
def
_save_image
(
self
,
image
,
path
,
format
=
'JPEG'
):
def
_save_image
(
self
,
image
,
path
,
format
=
'JPEG'
):
image
=
image
.
convert
(
'RGB'
)
with
open
(
path
,
'wb'
)
as
fp
:
with
open
(
path
,
'wb'
)
as
fp
:
image
.
save
(
fp
,
format
)
image
.
save
(
fp
,
format
)
...
...
flask_admin/model/fields.py
View file @
d2b6f20a
...
@@ -41,6 +41,26 @@ class InlineFieldList(FieldList):
...
@@ -41,6 +41,26 @@ class InlineFieldList(FieldList):
return
res
return
res
def
validate
(
self
,
form
,
extra_validators
=
tuple
()):
"""
Validate this FieldList.
Note that FieldList validation differs from normal field validation in
that FieldList validates all its enclosed fields first before running any
of its own validators.
"""
self
.
errors
=
[]
# Run validators on all entries within
for
subfield
in
self
.
entries
:
if
not
self
.
should_delete
(
subfield
)
and
not
subfield
.
validate
(
form
):
self
.
errors
.
append
(
subfield
.
errors
)
chain
=
itertools
.
chain
(
self
.
validators
,
extra_validators
)
self
.
_run_validation_chain
(
form
,
chain
)
return
len
(
self
.
errors
)
==
0
def
should_delete
(
self
,
field
):
def
should_delete
(
self
,
field
):
return
getattr
(
field
,
'_should_delete'
,
False
)
return
getattr
(
field
,
'_should_delete'
,
False
)
...
...
flask_admin/model/form.py
View file @
d2b6f20a
...
@@ -11,14 +11,14 @@ def converts(*args):
...
@@ -11,14 +11,14 @@ def converts(*args):
return
_inner
return
_inner
class
InlineFormAdmin
(
object
):
class
Inline
Base
FormAdmin
(
object
):
"""
"""
Settings for inline form administration.
Settings for inline form administration.
You can use this class to customize displayed form.
You can use this class to customize displayed form.
For example::
For example::
class MyUserInfoForm(InlineFormAdmin):
class MyUserInfoForm(Inline
Base
FormAdmin):
form_columns = ('name', 'email')
form_columns = ('name', 'email')
"""
"""
_defaults
=
[
'form_base_class'
,
'form_columns'
,
'form_excluded_columns'
,
'form_args'
,
'form_extra_fields'
]
_defaults
=
[
'form_base_class'
,
'form_columns'
,
'form_excluded_columns'
,
'form_args'
,
'form_extra_fields'
]
...
@@ -72,7 +72,7 @@ class InlineFormAdmin(object):
...
@@ -72,7 +72,7 @@ class InlineFormAdmin(object):
pass
pass
class
Inline
ModelFormAdmin
(
Inlin
eFormAdmin
):
class
Inline
FormAdmin
(
InlineBas
eFormAdmin
):
"""
"""
Settings for inline form administration. Used by relational backends (SQLAlchemy, Peewee), where model
Settings for inline form administration. Used by relational backends (SQLAlchemy, Peewee), where model
class can not be inherited from the parent model definition.
class can not be inherited from the parent model definition.
...
@@ -86,7 +86,7 @@ class InlineModelFormAdmin(InlineFormAdmin):
...
@@ -86,7 +86,7 @@ class InlineModelFormAdmin(InlineFormAdmin):
"""
"""
self
.
model
=
model
self
.
model
=
model
super
(
Inline
Model
FormAdmin
,
self
)
.
__init__
(
**
kwargs
)
super
(
InlineFormAdmin
,
self
)
.
__init__
(
**
kwargs
)
class
ModelConverterBase
(
object
):
class
ModelConverterBase
(
object
):
...
@@ -173,8 +173,8 @@ class InlineModelConverterBase(object):
...
@@ -173,8 +173,8 @@ class InlineModelConverterBase(object):
- Model class
- Model class
"""
"""
if
isinstance
(
p
,
tuple
):
if
isinstance
(
p
,
tuple
):
return
Inline
Model
FormAdmin
(
p
[
0
],
**
p
[
1
])
return
InlineFormAdmin
(
p
[
0
],
**
p
[
1
])
elif
isinstance
(
p
,
Inline
Model
FormAdmin
):
elif
isinstance
(
p
,
InlineFormAdmin
):
return
p
return
p
return
None
return
None
...
...
flask_admin/static/admin/js/form.js
View file @
d2b6f20a
...
@@ -63,7 +63,7 @@
...
@@ -63,7 +63,7 @@
this
.
applyGlobalStyles
=
function
(
parent
)
{
this
.
applyGlobalStyles
=
function
(
parent
)
{
$
(
'[data-role=select2]'
,
parent
).
select2
({
width
:
'resolve'
});
$
(
'[data-role=select2]'
,
parent
).
select2
({
width
:
'resolve'
});
$
(
'[data-role=select2blank]'
,
parent
).
select2
({
allowClear
:
true
,
width
:
'resolve'
});
$
(
'[data-role=select2blank]'
,
parent
).
select2
({
allowClear
:
true
,
width
:
'resolve'
});
$
(
'[data-role=select2tags]'
,
parent
).
select2
({
tags
:
[]
,
tokenSeparators
:
[
','
],
width
:
'resolve'
});
$
(
'[data-role=select2tags]'
,
parent
).
select2
({
multiple
:
true
,
tokenSeparators
:
[
','
],
width
:
'resolve'
});
$
(
'[data-role=datepicker]'
,
parent
).
datepicker
();
$
(
'[data-role=datepicker]'
,
parent
).
datepicker
();
$
(
'[data-role=datetimepicker]'
,
parent
).
datepicker
({
displayTime
:
true
});
$
(
'[data-role=datetimepicker]'
,
parent
).
datepicker
({
displayTime
:
true
});
};
};
...
...
flask_admin/templates/admin/model/inline_form.html
View file @
d2b6f20a
{% import 'admin/lib.html' as lib with context %}
{% import 'admin/lib.html' as lib with context %}
<div
class=
"
inline-form
"
>
<div
class=
"
fa-inline-field
"
>
{{ lib.render_form_fields(field, False) }}
{{ lib.render_form_fields(field, False) }}
</div>
</div>
flask_admin/tests/mongoengine/test_basic.py
View file @
d2b6f20a
...
@@ -259,7 +259,7 @@ def test_subdocument_config():
...
@@ -259,7 +259,7 @@ def test_subdocument_config():
def
test_subdocument_class_config
():
def
test_subdocument_class_config
():
app
,
db
,
admin
=
setup
()
app
,
db
,
admin
=
setup
()
from
flask.ext.admin.
model.form
import
InlineFormAdmin
from
flask.ext.admin.
contrib.mongoengine
import
EmbeddedForm
class
Comment
(
db
.
EmbeddedDocument
):
class
Comment
(
db
.
EmbeddedDocument
):
name
=
db
.
StringField
(
max_length
=
20
,
required
=
True
)
name
=
db
.
StringField
(
max_length
=
20
,
required
=
True
)
...
@@ -269,7 +269,7 @@ def test_subdocument_class_config():
...
@@ -269,7 +269,7 @@ def test_subdocument_class_config():
test1
=
db
.
StringField
(
max_length
=
20
)
test1
=
db
.
StringField
(
max_length
=
20
)
subdoc
=
db
.
EmbeddedDocumentField
(
Comment
)
subdoc
=
db
.
EmbeddedDocumentField
(
Comment
)
class
EmbeddedConfig
(
InlineFormAdmin
):
class
EmbeddedConfig
(
EmbeddedForm
):
form_columns
=
(
'name'
,)
form_columns
=
(
'name'
,)
# Check only
# Check only
...
...
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