Flask-Admin

Flask-Admin aims to be a flexible, customizable web-based interface to your datastore. Currently, Flask-Admin only works with SQLAlchemy declarative models but support for additional datastores will be added in future versions.

Note

Flask-Admin will only work with versions of Flask 0.7 or above.

How it works

Create some SQLAlchemy declarative models using SQLAlchemy or Flask-SQLAlchemy:

 engine = create_engine('sqlite://', convert_unicode=True)
 Base = declarative_base(bind=engine)

 class Student(Base):
     __tablename__ = 'student'

     id = Column(Integer, primary_key=True)
     name = Column(String(120), unique=True)

     def __repr__(self):
         return self.name

class Teacher(Base):
     __tablename__ = 'teacher'

     id = Column(Integer, primary_key=True)
     name = Column(String(120), unique=True)

     def __repr__(self):
         return self.name

Note

The __repr__ method of your model class will be used to describe specific instances of your models models in things like the list view. If you don’t set it the default __repr__ method will look something like <__main__.Student object at 0x1bb1490>, which won’t be very useful for distinguishing which model instance is which.

Then create a blueprint using those models and your sqlalchemy session:

db_session = scoped_session(sessionmaker(
    autocommit=False, autoflush=False,
    bind=engine))

admin_blueprint = admin.create_admin_blueprint(
     (Student, Teacher), db_session)

The first argument to create_admin_blueprint can have two forms: it can either be some python iterable like a list or tuple, or it can be a python module that contains your models. The second argument is the sqlalchemy session that will be used to access the database. By default, Flask-Admin will not expose the primary keys of your models. This is usually a good idea if you are using a primary key that doesn’t have any meaning outside of the database, like an auto-incrementing integer, because changing a primary key changes the nature of foreign key relationships. If you want to expose primary key, set exclude_pks=False in the create_admin_blueprint call.

Next, register this blueprint on your Flask app:

app = Flask(__name__)
app.register_blueprint(admin_blueprint, url_prefix='/admin')

Now the admin interface is set up. If you are running the app with the built-in development server via app.run(), then it would be available at http://localhost:5000/admin . See the examples directory of the flask-admin source code for some applications that that demonstrate ideas of how to configure the admin.

A note on __init__

Your model classes must be able to be initialized without any arguments. For example, this works because the name argument is optional:

class Person(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String(120), unique=True)

    def __init__(self, name=None):
        self.name = name

    def __repr__(self):
        return self.name

But the following will not work because in this latter case, the __init__ method of User() requires a name:

class Person(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String(120), unique=True)

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return self.name

Flask-Admin Endpoints

If you want to refer to views in Flask-Admin, the following endpoints are available:

url_for(‘admin.index’)
returns the url for the index view
url_for(‘admin.list_view’, model_name=’some_model’)
returns the list view for a given model
url_for(‘admin.edit’, model_name=’some_model’, model_key=primary_key)
returns the url for the page used for editing a specific model instance
url_for(‘admin.add’, model_name=’some_model’)
returns the url for the adding a new model instance
url_for(‘admin.delete’, model_name=’some_model’, model_key=primary_key)
returns the url for the page used for deleting a specific model instance

Note

You can use the name argument in create_admin_blueprint() to set the name of the blueprint. For example if name="my_named_admin", then the endpoint for the index becomes 'my_named_admin.index'. This is necessary if you are going to use multiple distinct admin blueprints within the same app.

Custom Templates and Static Files

Using Flask blueprints makes customizing the admin interface really easy. Flask-Admin comes with a default set of templates and static files. You can customize as much of the interface as you’d like by just overriding any files you’d like to change. To do this, just create them in the templates and/or static directories of your app. Refer to the documentation on Flask blueprints for more. There is also an example of this in examples/authentication/view_decorator.py

Custom Forms

Flask-Admin uses the WTForms library to automatically generate the form that will be used to add a new instance of a model or edit an existing model instance. There may be cases where the automatically generated form isn’t what you want, so you can also create a custom form for Flask-Admin to use for a given model.

For example, consider the following model of a User that stores hashed passwords:

Base = declarative_base()

class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    username = Column(String(80), unique=True)
    _password_hash = Column('password', String(80), nullable=False)
    is_active = Column(Boolean, default=True)

    def __init__(self, username="", password="", is_active=True):
        self.username = username
        self.password = password
        self.is_active = is_active

    def check_password(self, password):
        return check_password_hash(self.pw_hash, password)

    @property
    def password(self):
        return self._password_hash

    @password.setter
    def password(self, password):
        self._password_hash = generate_password_hash(password)

    password = synonym('_password_hash', descriptor=password)

    def __repr__(self):
        return self.username

To allow this model to be used with a typical password and confirmation field form, you could create the following form:

class UserForm(Form):
    """
    Form for creating or editting User object (via the admin). Define
    any handling of fields here. This form class also has precedence
    when rendering forms to a webpage, so the model-generated fields
    will come after it.
    """
    username = TextField(u'User name',
                         [validators.required(),
                          validators.length(max=80)])
    password = PasswordField('Change Password',
                             [validators.optional(),
                              validators.equal_to('confirm_password')])
    confirm_password = PasswordField()
    is_active = BooleanField(default=True)

And just use the model_forms argument when calling create_admin_blueprint to associate this form with the User model:

admin_blueprint = admin.create_admin_blueprint(
    (User,), db_session, model_forms={'User': UserForm})

Now the UserForm will be used for editing and adding a new user. If the form passes the validation checks, then password will propagate to the User model and will be hashed and stored the password in the database.

Note

Due to the way that forms are generated, the order of input fields is difficult to control. This is something that is expected to improve in future versions, but for now a custom form is also the only way to specify the order of form fields.

API

flaskext.admin.create_admin_blueprint(models, db_session, name='admin', model_forms=None, exclude_pks=True, list_view_pagination=25, view_decorator=None, **kwargs)

Returns a blueprint that provides the admin interface views. The blueprint that is returned will still need to be registered to your flask app. Additional parameters will be passed to the blueprint constructor.

The parameters are:

models
Either a module or an iterable that contains the SQLAlchemy models that will be made available through the admin interface.
db_session
A SQLAlchemy session that has been set up and bound to an engine. See the documentation on using Flask with SQLAlchemy for more information on how to set that up.
name
Specify the name for your blueprint. The name of the blueprint preceeds the view names of the endpoints, if for example you want to refer to the views using url_for(). If you are using multiple admin blueprints, it is necessary to set this value to something different for each admin module so the admin templates can find the correct views.
model_forms
A dict with model names as keys, mapped to WTForm Form objects that should be used as forms for creating and editing instances of these models.
exclude_pks
A Boolean value that specifies whether or not to automatically exclude fields representing the primary key from Flask-Admin rendered forms. The default is True.
list_view_pagination
The number of model instances that will be shown in the list view if there are more than this number of model instances.
view_decorator
A decorator function that will be applied to each admin view function. In particular, you might want to set this to a decorator that handles authentication (e.g. login_required). See the authentication/view_decorator.py for an example of how this might be used.
Fork me on GitHub