After almost 6 months of development time (with breaks, obviously), I'm happy to announce new version of the Flask-Admin package.
So, what's new?
Python 3 Support
Flask-Admin (and Flask-BabelEx) are now Python 3 compatible. I only tested them with Python 3.3, so can't guarantee that they'll work on older Python 3 versions.
All Flask-Admin features work as expected except of MongoEngine and Peewee backends, as their dependencies are not Python 3 compatible yet.
No More Flask-WTF
Flask-Admin is no longer uses Flask-WTF for the forms. This was done for few reasons: Flask-WTF was undergoing some significant API changes, was not Python 3 compatible and was additional dependency that I had to manage.
Starting with 1.0.7, Flask-Admin will use vanilla WTForms Form class with option to use any other base class if required.
Redis CLI
Now it is possible to run redis commands straight from Flask-Admin interface. Very convenient when you don't have access to redis console for whatever reason. Looks like this:
Example is here.
AJAX Foreign Key Loading
Starting from this version, it is possible to populate foreign-key drop-downs using AJAX calls. This feature should significantly improve Flask-Admin performance when working with large datasets.
Here is snippet from SQLAlchemy example
class PostAdmin(sqla.ModelView):
# .. skipped for brevity
form_ajax_refs = {
'user': {
'fields': (User.username, User.email)
},
'tags': {
'fields': (Tag.name,)
}
}
In this example, user and tags are foreign keys in the Post model. Without form_ajax_refs, Flask-Admin will pre-populate drop-downs with all possible users and all possible tags. If there are lots of users in the database and few thousand tags defined, create and edit pages will be huge.
With form_ajax_refs in place, Flask-Admin will make AJAX calls to get list of visible based on user input. For User model it will filter related models against username and email fields. For Tag model, it will filter on name field.
AJAX data loader is very configurable - it is possible to implement custom filtering logic if necessary.
Form Rendering Rules
Flask-Admin had very simple form rendering logic since the beginning - it was looping over form fields and rendering them one by one.
In this version, form rendering is now separate from the form definition. It is possible to rearrange fields, add HTML in-between fields without changing templates, override how fields are rendered and so on.
Here is simplified example that shows how to use the rules:
from flask.ext.admin.form import rules
from flask.ext.admin.contrib import sqla
class RuleView(sqla.ModelView):
form_create_rules = [
# Header and four fields. Email field will go above phone field.
rules.FieldSet(('first_name', 'last_name', 'email', 'phone'), 'Personal'),
# Separate header and few fields
rules.Header('Address'),
rules.Field('address'),
# String is resolved to form field, so there's no need to explicitly
# use `rules.Field`
'city',
'zip',
# Call `wrap` macro
rules.Container('wrap', rules.Field('notes'))
]
# Use same rule set for edit page
form_edit_rules = form_create_rules
This is snippet from forms example. When executed, form will look like:
Documentation is here.
MongoEngine Improvements
There are few new features in MongoEngine backend. Biggest ones - nested document configuration and GridFS support for file and image uploads.
Nested document configuration
Before this version, it was impossible to change form generation options for embedded documents. Now there is form_subdocuments field that configures Flask-Admin behavior when scaffolding forms for child models.
For example:
class Name(db.EmbeddedDocument):
name = db.StringField(max_length=20, required=True)
code = db.StringField(max_length=10)
class Post(db.Product):
info = db.StringField(max_length=20, required=True)
name = db.EmbeddedDocumentField(Name)
class PostView(ModelView):
form_subdocuments = {
'name': {
'form_rules': ('name', rules.HTML('<hr>'), 'code')
}
}
GridFS support
There are two new WTForms fields that handle file and image uploads and store them as GridFS objects in the document. They work in a same way as file-based file and image upload fields which will be explained below.
Inline Model Improvements
Before version 1.0.7, inline models were bolted on - hard to configure, not flexible, it was impossible to preprocess inline models before saving, etc.
In this version, inline model logic was moved to separate WTForm fields and whole inline model subsystem is much more configurable now.
FileUploadField and ImageUploadField
These two fields solve most common task when managing images and files: they handle file uploads, put them into dedicated directory and store relative path to the uploaded file in a model field.
ImageUploadField, with help of PIL, can verify if uploaded image is valid and generate image thumbnail.
These fields are very configurable and should cover most of the file and image related operations. Check documentation for more information.
Additional form columns
New form_extra_columns allows adding new WTForm fields to automatically generated model form. It is no longer necessary to override scaffold_form to contribute fields.
Complete Change Log
- Python 3 compatibility fixes
- Redis CLI
- Dropped Flask-WTF dependency
- Upgraded to Select2 3.4.0
- Additional unit tests
- Separate loggers for each Flask-Admin component
- New, much more configurable datetime picker
- Spanish translation
- Form rendering rules
- Models: AJAX drop-down population for related models
- Models: Filter options can be translated
- Models: on_model_change now accepts third parameter is_created
- Models: New configurarion property form_extra_columns
- Models: Proper child field error highlighting
- Models: Save and continue button for edit views
- Models: FileUploadField and ImageUploadField
- Models: If Flask is running in debug mode, rethrow all exceptions
- Models: Backrefs are now displayed by default
- Models: If there are no models in the list view, message will be displayed
- MongoEngine: GridFS support for file and image uploads
- MongoEngine: Backend supports form_overrides, choices and other field configuration properties
- MongoEngine: URLField and EmailField are now searchable
- MongoEngine: Embedded document configuration
- SQLAlchemy: Backend was renamed as flask.ext.admin.contrib.sqla
- SQLAlchemy: Automatic join for many-to-many relations
- SQLAlchemy: Fixed ambiguous primary key when building complex search query in SQLAlchemy backend
- SQLAlchemy: Use joinedload for related model instead of subqueryload for performance reasons
- SQLAlchemy: Improved inline model handling logic
- SQLAlchemy: Initial multi-pk support for inherited models
- SQLAlchemy: BigInt filtering support
- Peewee: Backend was renamed as flask.ext.admin.contrib.peewee