Eat at Joe's

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:

Redis CLI

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:

Form rendering rules

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.

ImageUploadField example

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

blog comments powered by Disqus