Flask-Admin comes with SQLAlchemy ORM backend.
Notable features:
- SQLAlchemy 0.6+ support
- Paging, sorting, filters
- Proper model relationship handling
- Inline editing of related models
In order to use SQLAlchemy model scaffolding, you need to have:
If you use Flask-SQLAlchemy, this is how you initialize Flask-Admin and get session from the SQLAlchemy object:
from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.admin import Admin from flask.ext.admin.contrib.sqla import ModelView app = Flask(__name__) # .. read settings db = SQLAlchemy(app) # .. model declarations here if __name__ == '__main__': admin = Admin(app) # .. add ModelViews # admin.add_view(ModelView(SomeModel, db.session))
Using previous template, lets create simple model:
# .. flask initialization db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) email = db.Column(db.String(128)) if __name__ == '__main__': admin = Admin(app) admin.add_view(ModelView(User, db.session)) db.create_all() app.run('0.0.0.0', 8000)
If you will run this example and open http://localhost:8000/, you will see that Flask-Admin generated administrative page for the model:
You can add new models, edit existing, etc.
List view can be customized in different ways.
First of all, you can use various class-level properties to configure what should be displayed and how. For example, :attr:`~flask.ext.admin.contrib.sqla.ModelView.column_list` can be used to show some of the column or include extra columns from related models.
For example:
class UserView(ModelView): # Show only name and email columns in list view column_list = ('name', 'email') # Enable search functionality - it will search for terms in # name and email fields column_searchable_list = ('name', 'email') # Add filters for name and email columns column_filters = ('name', 'email')
Alternatively, you can override some of the :class:`~flask.ext.admin.contrib.sqla.ModelView` methods and implement your custom logic.
For example, if you need to contribute additional field to the generated form, you can do something like this:
class UserView(ModelView): def scaffold_form(self): form_class = super(UserView, self).scaffold_form() form_class.extra = TextField('Extra') return form_class
Check :doc:`api/mod_contrib_sqla` documentation for list of configuration properties and methods.
Flask-Admin has limited support for models with multiple primary keys. It only covers specific case when all but one primary keys are foreign keys to another model. For example, model inheritance following this convention.
Lets Model a car with its tyres:
class Car(db.Model): __tablename__ = 'cars' id = db.Column(db.Integer, primary_key=True, autoincrement=True) desc = db.Column(db.String(50)) def __unicode__(self): return self.desc class Tyre(db.Model): __tablename__ = 'tyres' car_id = db.Column(db.Integer, db.ForeignKey('cars.id'), primary_key=True) tyre_id = db.Column(db.Integer, primary_key=True) car = db.relationship('Car', backref='tyres') desc = db.Column(db.String(50))
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
.
To be able to CRUD the Tyre
class, you need to enumerate columns when defining the AdminView:
class TyreAdmin(sqla.ModelView): form_columns = ['car', 'tyre_id', 'desc']
The form_columns
needs to be explicit, as per default only one primary key is displayed.
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 proper error message and you can change the data in the form. When the application has been started with debug=True
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.
Flask-Admin comes with relatively advanced example, which you can see here.