Commit ebe0aee1 authored by Petrus J.v.Rensburg's avatar Petrus J.v.Rensburg

Setup new sections. Move existing copy into place.

parent 53690bfb
Adding your own views
===========
Standalone views
------------
Now, lets add an administrative view. The next example will result in two items appearing in the navbar menu: *Home*
and *Hello*. To do this, you need to derive from the :class:`~flask_admin.base.BaseView` class::
from flask import Flask
from flask_admin 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()
One important restriction on admin views is that each view class should have a default page-view method with a root
url, '/'. The following example is correct::
class MyView(BaseView):
@expose('/')
def index(self):
return self.render('index.html')
but, this wouldn't work::
class MyView(BaseView):
@expose('/index/')
def index(self):
return self.render('index.html')
Now, create a new *index.html* file with following content::
{% extends 'admin/master.html' %}
{% block body %}
Hello World from MyView!
{% endblock %}
and place it in a *templates* directory. To maintain a consistent look and feel, all administrative pages should extend
the *admin/master.html* template.
You should now see your new admin page in action on the *Hello* page
.. image:: images/quickstart/quickstart_2.png
:width: 640
:target: ../_images/quickstart_2.png
To add another level of menu items, you can specify a value for the *category* parameter when passing admin views to
the Admin instance. The category specifies the name of the top-level menu item, and all of the views that are associated
with it, will be accessible from a drop-down menu. For example::
from flask import Flask
from flask_admin 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
.. image:: images/quickstart/quickstart_3.png
:width: 640
:target: ../_images/quickstart_3.png
Overriding specific model views
------------------
\ No newline at end of file
Authorisation & permissions
===========
HTTP Basic Auth
------------
Using Flask-Security
--------------------
Customising builtin views
===========
Image fields
-----------
HTML fields
-----------
List view options
---------------
Form view options
---------------
Database backends
=================
The purpose of Flask-Admin is to help you manage your data. For this, it needs some database backend in order to be
able to access that data in the first place. At present, there are five different backends for you to choose
from, depending on which database you would like to use for your application.
.. toctree::
:maxdepth: 2
db_sqla
db_geoa
db_mongoengine
db_peewee
db_pymongo
If you don't know where to start, but you're familiar with relational databases, then you should probably look at using
`SQLAlchemy`_. It is a full-featured toolkit, with support for SQLite, PostgreSQL, MySQL,
Oracle and MS-SQL amongst others. It really comes into its own once you have lots of data, and a fair amount of
relations between your data models. If you want to track spatial data like latitude/longitude
points, you should look into `GeoAlchemy`_, as well.
If you're looking for something simpler, or your data models are reasonably self-contained, then
`MongoEngine`_ could be a better option. It is a python wrapper around the popular
*NoSQL* database called `MongoDB`_.
Of course, if you feel that there's an awesome database wrapper that is missing from the list above, we'd greatly
appreciate it if you could write the plugin for it and submit it as a pull request. A special section of these docs
are dedicated to helping you through this process. See :doc:`model_guidelines`.
.. _SQLAlchemy: http://www.sqlalchemy.org/
.. _GeoAlchemy: http://geoalchemy-2.readthedocs.org/
.. _MongoEngine: http://mongoengine.org/
.. _MongoDB: http://www.mongodb.org/
GeoAlchemy backend
==================
If you want to store spatial information in a GIS database, Flask-Admin has
you covered. The `GeoAlchemy`_ backend extends the SQLAlchemy backend (just as
GeoAlchemy extends SQLAlchemy) to give you a pretty and functional map-based
editor for your admin pages.
Notable features:
- Uses the amazing `Leaflet`_ Javascript library for displaying maps,
with map data from `Mapbox`_
- Uses `Leaflet.Draw`_ for editing geographic information interactively,
including points, lines, and polygons
- Graceful fallback to editing `GeoJSON`_ data in a ``<textarea>``, if the
user has turned off Javascript
- Works with a `Geometry`_ SQL field that is integrated with `Shapely`_ objects
Getting Started
---------------
GeoAlchemy is based on SQLAlchemy, so you'll need to complete the "getting started"
directions for SQLAlchemy backend first. For GeoAlchemy, you'll also need a
map ID from `Mapbox`_, a map tile provider. (Don't worry, their basic plan
is free, and works quite well.) Then, just include the map ID in your application
settings::
app = Flask(__name__)
app.config['MAPBOX_MAP_ID'] = "example.abc123"
To use the v4 of their API (the default is v3):::
app.config['MAPBOX_ACCESS_TOKEN'] = "pk.def456"
.. note::
Leaflet supports loading map tiles from any arbitrary map tile provider, but
at the moment, Flask-Admin only supports Mapbox. If you want to use other
providers, make a pull request!
Creating simple model
---------------------
GeoAlchemy comes with a `Geometry`_ field that is carefully divorced from the
`Shapely`_ library. Flask-Admin will use this field so that there are no
changes necessary to other code. ``ModelView`` should be imported from
``geoa`` rather than the one imported from ``sqla``::
from geoalchemy2 import Geometry
from flask_admin.contrib.geoa import ModelView
# .. flask initialization
db = SQLAlchemy(app)
class Location(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
point = db.Column(Geometry("POINT"))
if __name__ == '__main__':
admin = Admin(app)
admin.add_view(ModelView(User, db.session))
db.create_all()
app.run('0.0.0.0', 8000)
Limitations
-----------
There's currently no way to sort, filter, or search on geometric fields
in the admin. It's not clear that there's a good way to do so.
If you have any ideas or suggestions, make a pull request!
.. _GeoAlchemy: http://geoalchemy-2.readthedocs.org/
.. _Leaflet: http://leafletjs.com/
.. _Leaflet.Draw: https://github.com/Leaflet/Leaflet.draw
.. _Shapely: http://toblerity.org/shapely/
.. _Mapbox: https://www.mapbox.com/
.. _GeoJSON: http://geojson.org/
.. _Geometry: http://geoalchemy-2.readthedocs.org/en/latest/types.html#geoalchemy2.types.Geometry
Form rendering rules
====================
Before version 1.0.7, all model backends were rendering the *create* and *edit* forms
using a special Jinja2 macro, which was looping over the fields of a WTForms form object and displaying
them one by one. This works well, but it is difficult to customize.
Starting from version 1.0.7, Flask-Admin supports form rendering rules, to give you fine grained control of how
the forms for your modules should be displayed.
The basic idea is pretty simple: the customizable rendering rules replace a static macro, so that you can tell
Flask-Admin how each form should be rendered. As an extension, however, the rendering rules also let you do a
bit more: You can use them to output HTML, call Jinja2 macros, render fields and so on.
Essentially, form rendering rules abstract the rendering, so that it becomes separate from the form definition. So,
for example, it no longer matters in which sequence your form fields are defined.
Getting started
---------------
To start using the form rendering rules, put a list of form field names into the `form_create_rules`
property one of your admin views::
class RuleView(sqla.ModelView):
form_create_rules = ('email', 'first_name', 'last_name')
In this example, only three fields will be rendered and `email` field will be above other two fields.
Whenever Flask-Admin sees a string value in `form_create_rules`, it automatically assumes that it is a
form field reference and creates a :class:`flask_admin.form.rules.Field` class instance for that field.
Lets say we want to display some text between the `email` and `first_name` fields. This can be accomplished by
using the :class:`flask_admin.form.rules.Text` class::
from flask_admin.form import rules
class RuleView(sqla.ModelView):
form_create_rules = ('email', rules.Text('Foobar'), 'first_name', 'last_name')
Built-in rules
--------------
Flask-Admin comes with few built-in rules that can be found in the :mod:`flask_admin.form.rules` module:
======================================================= ========================================================
Form Rendering Rule Description
======================================================= ========================================================
:class:`flask_admin.form.rules.BaseRule` All rules derive from this class
:class:`flask_admin.form.rules.NestedRule` Allows rule nesting, useful for HTML containers
:class:`flask_admin.form.rules.Text` Simple text rendering rule
:class:`flask_admin.form.rules.HTML` Same as `Text` rule, but does not escape the text
:class:`flask_admin.form.rules.Macro` Calls macro from current Jinja2 context
:class:`flask_admin.form.rules.Container` Wraps child rules into container rendered by macro
:class:`flask_admin.form.rules.Field` Renders single form field
:class:`flask_admin.form.rules.Header` Renders form header
:class:`flask_admin.form.rules.FieldSet` Renders form header and child rules
======================================================= ========================================================
Enabling CSRF Validation
------------------------
Adding CSRF validation will require overriding the :class:`flask_admin.form.BaseForm` by using :attr:`flask_admin.model.BaseModelView.form_base_class`.
WTForms >=2::
from wtforms.csrf.session import SessionCSRF
from wtforms.meta import DefaultMeta
from flask import session
from datetime import timedelta
from flask_admin import form
from flask_admin.contrib import sqla
class SecureForm(form.BaseForm):
class Meta(DefaultMeta):
csrf = True
csrf_class = SessionCSRF
csrf_secret = b'EPj00jpfj8Gx1SjnyLxwBBSQfnQ9DJYe0Ym'
csrf_time_limit = timedelta(minutes=20)
@property
def csrf_context(self):
return session
class ModelAdmin(sqla.ModelView):
form_base_class = SecureForm
For WTForms 1, you can use use Flask-WTF's Form class::
import os
import flask
import flask_wtf
import flask_admin
import flask_sqlalchemy
from flask_admin.contrib.sqla import ModelView
DBFILE = 'app.db'
app = flask.Flask(__name__)
app.config['SECRET_KEY'] = 'Dnit7qz7mfcP0YuelDrF8vLFvk0snhwP'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + DBFILE
app.config['CSRF_ENABLED'] = True
flask_wtf.CsrfProtect(app)
db = flask_sqlalchemy.SQLAlchemy(app)
admin = flask_admin.Admin(app, name='Admin')
class MyModelView(ModelView):
# Here is the fix:
form_base_class = flask_wtf.Form
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String)
password = db.Column(db.String)
if not os.path.exists(DBFILE):
db.create_all()
admin.add_view( MyModelView(User, db.session, name='User') )
app.run(debug=True)
Further reading
---------------
For additional documentation, check :mod:`flask_admin.form.rules` module source code (it is quite short) and
look at the `forms example <https://github.com/flask-admin/flask-admin/tree/master/examples/forms>`_ on GitHub.
Getting started
===========
Initialization
--------------
To start using Flask-Admin, you have to create a :class:`~flask_admin.base.Admin` class instance and associate it
with the Flask
application instance::
from flask import Flask
from flask_admin 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/ <http://localhost:5000/admin/>`_,
you should see an empty "Home" page with a navigation bar on top
.. image:: images/quickstart/quickstart_1.png
:target: ../_images/quickstart_1.png
You can change the application name by passing a value for the *name* parameter to the
:class:`~flask_admin.base.Admin` class constructor::
admin = Admin(app, name='My App')
As an alternative to passing a Flask application object to the Admin constructor, you can also call the
:meth:`~flask_admin.base.Admin.init_app` function, after the Admin instance has been initialized::
admin = Admin(name='My App')
# Add views here
admin.init_app(app)
Adding Model Views
-----------
Model views allow you to add dedicated admin pages for each of the models in your database. Do this by creating
instances of the *ModelView* class, which you can import from one of Flask-Admin's built-in ORM backends. An example
is the SQLAlchemy backend, which you can use as follows::
from flask_admin.contrib.sqla import ModelView
# Flask and Flask-SQLAlchemy initialization here
admin = Admin(app)
admin.add_view(ModelView(User, db.session))
This creates an admin page for the *User* model. By default, the list view looks like
.. image:: images/quickstart/quickstart_4.png
:width: 640
:target: ../_images/quickstart_4.png
To customize these model views, you have two options: Either you can override the public properties of the *ModelView*
class, or you can override its methods.
For example, if you want to disable model creation and only show certain columns in the list view, you can do
something like::
from flask_admin.contrib.sqla import ModelView
# Flask and Flask-SQLAlchemy initialization here
class MyView(ModelView):
# Disable model creation
can_create = False
# Override displayed fields
column_list = ('login', 'email')
def __init__(self, session, **kwargs):
# You can pass name and other parameters if you want to
super(MyView, self).__init__(User, session, **kwargs)
admin = Admin(app)
admin.add_view(MyView(db.session))
Overriding form elements can be a bit trickier, but it is still possible. Here's an example of
how to set up a form that includes a column named *status* that allows only predefined values and
therefore should use a *SelectField*::
from wtforms.fields import SelectField
class MyView(ModelView):
form_overrides = dict(status=SelectField)
form_args = dict(
# Pass the choices to the `SelectField`
status=dict(
choices=[(0, 'waiting'), (1, 'in_progress'), (2, 'finished')]
))
It is relatively easy to add support for different database backends (Mongo, etc) by inheriting from
:class:`~flask_admin.model.BaseModelView`.
class and implementing database-related methods.
Please refer to :mod:`flask_admin.contrib.sqla` documentation on how to customize the behavior of model-based
administrative views.
Overriding the index page
-------------------------
...@@ -8,20 +8,94 @@ a way that the developer has total control of the look, feel and functionality o ...@@ -8,20 +8,94 @@ a way that the developer has total control of the look, feel and functionality o
Browse through the documentation below to learn more about what you can do with Flask-Admin. Or head over to Browse through the documentation below to learn more about what you can do with Flask-Admin. Or head over to
`our GitHub repository <http://github.com/flask-admin/flask-admin>`_ to find out how you can contribute to the project. `our GitHub repository <http://github.com/flask-admin/flask-admin>`_ to find out how you can contribute to the project.
This page gives a quick introduction to the Flask-Admin library. It is assumed that the reader has some prior
knowledge of the `Flask <http://flask.pocoo.org/>`_ framework.
If you're a Django user, you might also find the :doc:`django_migration` guide helpful.
Introduction
------------
The library is intended to be as flexible as possible. And the developer should
not need to monkey-patch anything to achieve desired functionality.
The library uses one simple, but powerful concept - administrative pieces are built as classes with
view methods.
For example, here is an 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')
If the user visits the *index* view, the *admin/myindex.html* template will be rendered. In the same way, visiting
the *test* view will result in the *admin/test.html* view being rendered.
So, how does this approach help in structuring an admin interface? With such building blocks, you're
implementing reusable functional pieces that are highly customizable.
For example, Flask-Admin provides a ready-to-use SQLAlchemy model interface. It is implemented as a
class which accepts two parameters: the model class and a database session. While it exposes some
class-level variables which change behavior of the interface (somewhat similar to django.contrib.admin),
nothing prohibits you from inheriting from it and overriding the form creation logic, database access methods
or extend existing functionality by adding more views.
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
quickstart getting_started
django_migration authorisation_and_permissions
templates customising_builtin_views
localization adding_your_own_views
tips advanced
db
model_guidelines
form_rules
api/index api/index
changelog
renamed_columns
Examples
--------
Flask-Admin comes with several examples, that will really help you get a grip on what's possible.
Browse through them in the GitHub repo, and then run them locally to get yourself up to speed in no time:
- `Simple views <https://github.com/flask-admin/Flask-Admin/tree/master/examples/simple>`_
Here we show how to add some simple custom views to your admin interface. They don't have to
be associated to any of your database models. You can fill them with whatever content you want.
- `Custom layout <https://github.com/flask-admin/Flask-Admin/tree/master/examples/layout>`_
Override some of the built-in templates to get complete control over the look and feel of your Admin interface. Either
while using the default Bootstrap 2, or the newer `Bootstrap 3 <https://github.com/flask-admin/Flask-Admin/tree/master/examples/layout_bootstrap3>`_.
- `SQLAlchemy model example <https://github.com/flask-admin/Flask-Admin/tree/master/examples/sqla>`_
Model-based views provide heaps of builtin goodness, making it really easy to get a set of the default CRUD views in place.
This example shows some of the basics.
- `SQLAlchemy model views with custom forms and file handling <https://github.com/flask-admin/Flask-Admin/tree/master/examples/forms>`_
Here, we show some of the more interesting things you can do with very little effort, including customizing the
builtin forms, and adding support for handling file/image uploads.
- `Flask-Login integration example <https://github.com/flask-admin/Flask-Admin/tree/master/examples/auth>`_
Use Flask-Login for authentication to hide some of your admin views behind a login wall.
- `Peewee model example <https://github.com/flask-admin/Flask-Admin/tree/master/examples/peewee>`_
Not so keen on SQLAlchemy? Perhaps you'd rather use Peewee?
- `MongoEngine model example <https://github.com/flask-admin/Flask-Admin/tree/master/examples/mongoengine>`_
... or check this example if MongoDB is more your style.
- `I18n and L10n with Flask-BabelEx <https://github.com/flask-admin/Flask-Admin/tree/master/examples/babel>`_
Do you need to make your Admin interface available in other languages? Luckily, Flask-Admin is built for just that kind of thing.
- `Redis terminal <https://github.com/flask-admin/Flask-Admin/tree/master/examples/rediscli>`_
If you use Redis for caching, then check this example to see how easy it is to add a Redis terminal to your Admin
interface, so you can reach your Redis instance straight from a browser.
Indices and tables Indices and tables
......
Localization
============
Flask-Admin makes it possible for you to serve your application in more than one language. To do this, it makes use of
the `Flask-BabelEx <http://github.com/flask-admin/flask-babelex/>`_ package for handling translations. This package is a
fork of the popular `Flask-Babel <http://github.com/mitshuhiko/flask-babel/>`_ package, with the following features:
1. It is API-compatible with Flask-Babel
2. It allows distribution of translations with Flask extensions
3. It aims to be more configurable than Flask-Babel
Currently *Flask-BabelEx* is the only supported way of enabling localization support in Flask-Admin.
How to enable localization
--------------------------
1. Install Flask-BabelEx::
pip install flask-babelex
2. Initialize Flask-BabelEx by creating instance of `Babel` class::
from flask import app
from flask_babelex import Babel
app = Flask(__name__)
babel = Babel(app)
3. Create a locale selector function::
@babel.localeselector
def get_locale():
# Put your logic here. Application can store locale in
# user profile, cookie, session, etc.
return 'en'
4. Initialize Flask-Admin as usual.
You can check the `babel` example to see localization in action. When running this example, you can change the
locale simply by adding a query parameter, like *?en=<locale name>* to the URL. For example, a French version of
the application should be accessible at:
`http://localhost:5000/admin/userview/?lang=fr <http://localhost:5000/admin/userview/?lang=fr>`_.
This diff is collapsed.
Renamed Columns
---------------
Starting from version 1.0.4, Flask-Admin uses different configuration
property names.
Please update your sources as support for old property names will be
removed in future Flask-Admin versions.
=========================== =============================
**Old Name** **New name**
--------------------------- -----------------------------
list_columns column_list
excluded_list_columns column_exclude_list
list_formatters column_formatters
list_type_formatters column_type_formatters
rename_columns column_labels
sortable_columns column_sortable_list
searchable_columns column_searchable_list
list_display_pk column_display_pk
auto_select_related column_auto_select_related
list_select_related column_select_related_list
list_display_all_relations column_display_all_relations
excluded_form_columns form_excluded_columns
disallowed_actions action_disallowed_list
=========================== =============================
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment