Flask-SuperAdmin¶
Flask-Superadmin he best admin interface framework for Flask. As good as Django admin.
Batteries included:
- Admin interface
- Scaffolding for MongoEngine, Django and SQLAlchemy
- File administrator (optional)
Requirements:
This package is a vitamined fork of Flask-Admin.
Quick Start¶
This page gives quick introduction to Flask-SuperAdmin library. It is assumed that reader has some prior knowledge of the Flask framework.
Introduction¶
While developing the library, I attempted to make it as flexible as possible. Developer should not monkey-patch anything to achieve desired functionality.
Library uses one simple, but powerful concept - administrative pieces are built as classes with view methods.
Here is absolutely valid administrative piece:
class MyView(BaseView):
@expose('/')
def index(self):
return self.render('admin/myindex.html')
@expose('/test/')
def test(self):
return self.render('admin/test.html')
So, how does it help structuring administrative interface? With such building blocks, you’re implementing reusable functional pieces that are highly customizable.
For example, Flask-SuperAdmin provides ready-to-use SQLAlchemy, Mongoengine and Django model interface. For SQLAlchemy it is implemented as a class which accepts two parameters: model and a database session, otherwise just the model parameter.
While it exposes some class-level variables which change behavior of the interface (somewhat similar to django.contrib.admin), nothing prohibits you from overriding form creation logic, database access methods or extending existing functionality.
Initialization¶
To start using Flask-SuperAdmin, you have to create Admin
class instance and associate it with the Flask
application instance:
from flask import Flask
from flask.ext.superadmin import Admin
app = Flask(__name__)
admin = Admin(app)
# Add administrative views here
app.run()
If you start this application and navigate to http://localhost:5000/admin/, you should see empty “Home” page with a navigation bar on top
You can change application name by passing name parameter to the Admin
class constructor:
admin = Admin(app, name='My App')
Name is displayed in the menu section.
You don’t have to pass Flask application object to the constructor - you can call init_app()
later:
admin = Admin(name='My App')
# Add views here
admin.init_app(app)
Adding views¶
Now, lets add an administrative view. To do this, you need to derive from BaseView
class:
from flask import Flask
from flask.ext.superadmin import Admin, BaseView, expose
class MyView(BaseView):
@expose('/')
def index(self):
return self.render('index.html')
app = Flask(__name__)
admin = Admin(app)
admin.add_view(MyView(name='Hello'))
app.run()
If you will run this example, you will see that menu has two items: Home and Hello.
Each view class should have default page - view method with ‘/’ url. Following code won’t work:
class MyView(BaseView):
@expose('/index/')
def index(self):
return self.render('index.html')
Now, create templates directory and then create new index.html file with following content:
{% extends 'admin/master.html' %}
{% block body %}
Hello World from MyView!
{% endblock %}
All administrative pages should derive from the ‘admin/master.html’ to maintain same look and feel.
If you will refresh ‘Hello’ administrative page again you should see greeting in the content section.
You’re not limited to top level menu. It is possible to pass category name and it will be used as a top menu item. For example:
from flask import Flask
from flask.ext.superadmin import Admin, BaseView, expose
class MyView(BaseView):
@expose('/')
def index(self):
return self.render('index.html')
app = Flask(__name__)
admin = Admin(app)
admin.add_view(MyView(name='Hello 1', endpoint='test1', category='Test'))
admin.add_view(MyView(name='Hello 2', endpoint='test2', category='Test'))
admin.add_view(MyView(name='Hello 3', endpoint='test3', category='Test'))
app.run()
Will look like this:
Authentication¶
By default, administrative interface is visible to everyone, as Flask-SuperAdmin does not make any assumptions about authentication system you’re using.
If you want to control who can access administrative views and who can not, derive from the administrative view class and implement is_accessible method. So, if you use Flask-Login and want to expose administrative interface only to logged in users, you can do something like this:
class MyView(BaseView):
def is_accessible(self):
return login.current_user.is_authenticated()
You can implement policy-based security, conditionally allow or disallow access to parts of the administrative interface and if user does not have access to the view, he won’t see menu item as well.
Generating URLs¶
Internally, view classes work on top of Flask blueprints, so you can use url_for with a dot prefix to get URL to a local view:
from flask import url_for
class MyView(BaseView):
@expose('/')
def index(self)
# Get URL for the test view method
url = url_for('.test')
return self.render('index.html', url=url)
@expose('/test/')
def test(self):
return self.render('test.html')
If you want to generate URL to the particular view method from outside, following rules apply:
1. You have ability to override endpoint name by passing endpoint parameter to the view class constructor:
admin = Admin(app)
admin.add_view(MyView(endpoint='testadmin'))
In this case, you can generate links by concatenating view method name with a endpoint:
url_for('testadmin.index')
2. If you don’t override endpoint name, it will use lower case class name. For previous example, code to get URL will look like:
url_for('myview.index')
3. For model-based views rule is different - it will take model class name, if endpoint name is not provided. Model-based views will be explained in the next section.
Model Views¶
Flask-SuperAdmin comes with built-in SQLAlchemy model administrative interface. It is very easy to use:
from flask.ext.superadmin import Admin
# Flask and Flask-SQLAlchemy initialization here
admin = Admin(app)
admin.register(User, session=db.session)
This will create administrative interface for User model with default settings.
Here is how default list view looks like:
If you want to customize model views, you have two options:
- Change behavior by overriding public properties that control how view works
- Change behavior by overriding methods
For example, if you want to disable model creation, show only ‘login’ and ‘email’ columns in the list view, you can do something like this:
from flask.ext.superadmin import Admin, model
# Flask and Flask-SQLAlchemy initialization here
class UserModel(model.ModelAdmin):
session = db.session
list_display = ('username','email')
admin = Admin(app)
admin.register(User, UserModel)
It is relatively easy to add support for different database backends by inheriting from BaseModelAdmin
.
class and implementing database-related methods.
Please refer to flask.ext.superadmin.model.mongoengine
documentation on how to customize behavior of model-based administrative views.
File Admin¶
Flask-SuperAdmin comes with another handy battery - file admin. It gives you ability to manage files on your server (upload, delete, rename, etc).
Here is simple example:
from flask.ext.superadmin import Admin
from flask.ext.superadmin.contrib.fileadmin import FileAdmin
import os.path as op
# Flask setup here
admin = Admin(app)
path = op.join(op.dirname(__file__), 'static')
admin.add_view(FileAdmin(path, '/static/', name='Static Files'))
Sample screenshot:
You can disable uploads, disable file or directory deletion, restrict file uploads to certain types and so on.
Check flask.ext.superadmin.contrib.fileadmin
documentation on how to do it.
Examples¶
Flask-SuperAdmin comes with a lot of samples:
Adding new model backend¶
If you want to implement new database backend to use with model views, follow steps found in this guideline.
There are few assumptions about models:
- Model has “primary key” - value which uniquely identifies one model in a data store. There’s no restriction on the data type or field name.
- Model has readable python properties
- It is possible to get list of models (optionally - sorted, filtered, etc) from data store
- It is possible to get one model by its primary key
Steps to add new model backend:
Create new class and derive it from
BaseModelAdmin
:class MyDbModel(BaseModelView): passBy default, all model views accept model class and it will be stored as
self.model
.
- PLEASE VIEW
ModelAdmin
for how to do a new backend.
Feel free ask questions if you have problem adding new model backend.
API¶
flask.ext.superadmin.base
¶
Base View¶
-
flask.ext.superadmin.base.
expose
(url='/', methods=('GET', ))[source]¶ Use this decorator to expose views in your view classes.
- url
- Relative URL for the view
- methods
- Allowed HTTP methods. By default only GET is allowed.
-
class
flask.ext.superadmin.base.
BaseView
(name=None, category=None, endpoint=None, url=None, static_folder=None)[source]¶ Base administrative view.
Derive from this class to implement your administrative interface piece. For example:
class MyView(BaseView): @expose('/') def index(self): return 'Hello World!'
Default view¶
-
class
flask.ext.superadmin.base.
AdminIndexView
(name=None, category=None, endpoint=None, url=None)[source]¶ Default administrative interface index page when visiting the
/admin/
URL.It can be overridden by passing your own view class to the
Admin
constructor:class MyHomeView(AdminIndexView): @expose('/') def index(self): return render_template('adminhome.html') admin = Admin(index_view=MyHomeView)
Default values for the index page are following:
- If name is not provided, ‘Home’ will be used.
- If endpoint is not provided, will use
admin
- Default URL route is
/admin
. - Automatically associates with static folder.
Admin¶
-
class
flask.ext.superadmin.base.
Admin
(app=None, name=None, url=None, index_view=None, translations_path=None)[source]¶ Collection of the views. Also manages menu structure.
-
locale_selector
(f)[source]¶ Installs locale selector for current
Admin
instance.Example:
def admin_locale_selector(): return request.args.get('lang', 'en') admin = Admin(app) admin.locale_selector(admin_locale_selector)
It is also possible to use the
@admin
decorator:admin = Admin(app) @admin.locale_selector def admin_locale_selector(): return request.args.get('lang', 'en')
Or by subclassing the
Admin
:class MyAdmin(Admin): def locale_selector(self): return request.args.get('lang', 'en')
Return menu hierarchy.
-
flask.ext.superadmin.model
¶
flask.ext.superadmin.form
¶
flask.ext.superadmin.tools
¶
flask.ext.superadmin.contrib.fileadmin
¶
-
class
flask.ext.superadmin.contrib.fileadmin.
FileAdmin
(base_path, base_url, name=None, category=None, endpoint=None, url=None)[source]¶ Simple file-management interface.
Requires two parameters:
- path
- Path to the directory which will be managed
- url
- Base URL for the directory. Will be used to generate static links to the files.
Sample usage:
admin = Admin() path = op.join(op.dirname(__file__), 'static') admin.add_view(FileAdmin(path, '/static/', name='Static Files')) admin.setup_app(app)
-
can_upload
= True¶ Is file upload allowed.
-
can_delete
= True¶ Is file deletion allowed.
-
can_delete_dirs
= True¶ Is recursive directory deletion is allowed.
-
can_mkdir
= True¶ Is directory creation allowed.
-
can_rename
= True¶ Is file and directory renaming allowed.
-
allowed_extensions
= None¶ List of allowed extensions for uploads, in lower case.
Example:
class MyAdmin(FileAdmin): allowed_extensions = ('swf', 'jpg', 'gif', 'png')
-
list_template
= 'admin/file/list.html'¶ File list template
-
upload_template
= 'admin/file/form.html'¶ File upload template
-
mkdir_template
= 'admin/file/form.html'¶ Directory creation (mkdir) template
-
rename_template
= 'admin/file/rename.html'¶ Rename template
-
get_base_path
()[source]¶ Return base path. Override to customize behavior (per-user directories, etc)
-
index
(*args, **kwargs)[source]¶ Index view method
- path
- Optional directory path. If not provided, will use base directory
-
is_accessible_path
(path)[source]¶ Verify if path is accessible for current user.
Override to customize behavior.
- path
- Relative path to the root
-
is_file_allowed
(filename)[source]¶ Verify if file can be uploaded.
Override to customize behavior.
- filename
- Source file name
-
mkdir
(*args, **kwargs)[source]¶ Directory creation view method
- path
- Optional directory path. If not provided, will use base directory