Commit 5ddba04f authored by Petrus J.v.Rensburg's avatar Petrus J.v.Rensburg

Clean up index page.

parent b6bcae27
Advanced Functionality
=================================
.. _extending-builtin-templates:
Extending the Builtin Templates
---------------------------------
****
By default, Flask-Admin uses three pre-defined templates for displaying your models in the admin-interface:
* `admin/model/list.html`
* `admin/model/create.html`
* `admin/model/edit.html`
All three of these extend the `admin/master.html` template, and you can override them by defining your own templates,
with the same path relative to your `templates` folder.
You could also choose to extend these templates, rather than overriding them. In this case you will need to
point your classes at your own templates, rather than letting them use the defaults. For example, your own template
for the *edit* views could be defined in `templates/my_edit_template.html` to look something like::
{% extends 'admin/model/edit.html' %}
{% block tail %}
{{ super() }}
...
{% endblock %}
And your classes could be made to use this template by setting the appropriate class property::
class MyModelView(ModelView):
edit_template = 'my_edit_template.html'
The three available properties are simply called `list_template`, `create_template` and `edit_template`.
Replacing Individual Form Fields
------------------------------------------
****
The `form_overrides` attribute allows you to replace individual fields within a form.
A common use-case for this would be to add a rich text editor, or to handle
file / image uploads that need to be tied to a field in your model.
Rich-Text Fields
**********************
To handle complicated text content, use a *WYSIWIG* text editor, like
`CKEditor <http://ckeditor.com/>`_ by subclassing some of the builtin WTForms
classes as follows::
from wtforms import TextAreaField
from wtforms.widgets import TextArea
class CKTextAreaWidget(TextArea):
def __call__(self, field, **kwargs):
if kwargs.get('class'):
kwargs['class'] += ' ckeditor'
else:
kwargs.setdefault('class', 'ckeditor')
return super(CKTextAreaWidget, self).__call__(field, **kwargs)
class CKTextAreaField(TextAreaField):
widget = CKTextAreaWidget()
class MessageAdmin(ModelView):
form_overrides = {
'body': CKTextAreaField
}
create_template = 'ckeditor.html'
edit_template = 'ckeditor.html'
For this to work, you would also need to create a template that extends the default
functionality by including the necessary CKEditor javascript on the `create` and
`edit` pages. Save this in `templates/ckeditor.html`::
{% extends 'admin/model/edit.html' %}
{% block tail %}
{{ super() }}
<script src="http://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.0.1/ckeditor.js"></script>
{% endblock %}
File & Image Fields
*******************
Flask-Admin comes with a builtin `FileUploadField` and `ImageUploadField`. To make use
of them, you'll need to specify an upload directory, and add them to the forms in question.
Image handling also requires you to have `Pillow <https://pypi.python.org/pypi/Pillow/2.8.2>`_ installed.
Have a look at the example at
https://github.com/flask-admin/Flask-Admin/tree/master/examples/forms.
If you are using the MongoEngine backend, Flask-Admin supports GridFS-backed image- and file uploads, done through WTForms fields. Documentation can be found
at :mod:`flask_admin.contrib.mongoengine.fields`.
If you just want to manage static files in a directory, without tying them to a database model, then
rather use the handy :ref:`File-Admin<file-admin>` plugin.
Initialisation
---------------
****
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::
......@@ -10,10 +112,11 @@ As an alternative to passing a Flask application object to the Admin constructor
# Add views here
admin.init_app(app)
****
Localization with Flask-Babelex
------------------------------------------
****
Enabling localization is relatively simple.
#. Install `Flask-BabelEx <http://github.com/mrjoes/flask-babelex/>`_ to do the heavy
......@@ -49,11 +152,12 @@ Enabling localization is relatively simple.
If the builtin translations are not enough, look at the `Flask-BabelEx documentation <https://pythonhosted.org/Flask-BabelEx/>`_
to see how you can add your own.
****
Handling Foreign Key relations inline
--------------------------------------------
****
Many-to-many relations
----------------------------------
......@@ -64,6 +168,8 @@ Many-to-many relations
Managing Files & Folders
--------------------------------
****
Flask-Admin comes with another handy battery - file admin. It gives you the ability to manage files on your server
(upload, delete, rename, etc).
......@@ -89,11 +195,11 @@ Sample screenshot:
You can disable uploads, disable file or directory deletion, restrict file uploads to certain types and so on.
Check :mod:`flask_admin.contrib.fileadmin` documentation on how to do it.
****
Managing geographical models
--------------------------------------
****
GeoAlchemy backend
If you want to store spatial information in a GIS database, Flask-Admin has
......@@ -173,11 +279,11 @@ If you have any ideas or suggestions, make a pull request!
.. _GeoJSON: http://geojson.org/
.. _Geometry: http://geoalchemy-2.readthedocs.org/en/latest/types.html#geoalchemy2.types.Geometry
****
Customising builtin forms via 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.
......@@ -233,10 +339,11 @@ Form Rendering Rule Description
:class:`flask_admin.form.rules.FieldSet` Renders form header and child rules
======================================================= ========================================================
Enabling CSRF Validation
-----------------------------
****
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::
......@@ -298,11 +405,14 @@ For WTForms 1, you can use use Flask-WTF's Form class::
app.run(debug=True)
****
Using different database backends
.. _database-backends:
Using Different 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.
......@@ -335,11 +445,11 @@ are dedicated to helping you through this process. See :doc:`model_guidelines`.
.. _MongoEngine: http://mongoengine.org/
.. _MongoDB: http://www.mongodb.org/
****
Migrating from Django
-------------------------
****
If you are used to `Django <https://www.djangoproject.com/>`_ and the *django-admin* package, you will find
Flask-Admin to work slightly different from what you would expect.
......@@ -469,5 +579,28 @@ and then point your class to this new template::
For list of available template blocks, check :doc:`templates`.
Adding a Redis console
--------------------------
****
Overriding the Form Scaffolding
---------------------------------
****
If you don't want to the use the built-in Flask-Admin form scaffolding logic, you are free to roll your own
by simply overriding :meth:`~flask_admin.model.base.scaffold_form`. For example, if you use
`WTForms-Alchemy <https://github.com/kvesteri/wtforms-alchemy>`_, you could put your form generation code
into a `scaffold_form` method in your `ModelView` class.
For SQLAlchemy, if the `synonym_property` does not return a SQLAlchemy field, then Flask-Admin won't be able to figure out what to
do with it, so it won't generate a form field. In this case, you would need to manually contribute your own field::
class MyView(ModelView):
def scaffold_form(self):
form_class = super(UserView, self).scaffold_form()
form_class.extra = TextField('Extra')
return form_class
......@@ -6,33 +6,38 @@ It offers freedom for you, the designer, to implement your project in a way that
particular application.
**Why Flask-Admin?** In a world of micro-services and APIs, Flask-Admin solves
the really boring problem of letting you quickly build an admin interface on top
of an existing data model. With little effort, it makes it possible for
you to manage your web service's data through a user-friendly interface.
the boring problem of building an admin interface on top
of an existing data model. With little effort, it lets
you manage your web service's data through a user-friendly interface.
Examples
==========
Flask-Admin comes with several examples that will help you get a grip on what's possible.
Have a look at http://examples.flask-admin.org/ to see them in action, or browse through the `examples` directory in the GitHub repository.
****
Getting Started
=================
Flask-Admin lets you build complicated interfaces by grouping individual views
**How does it work?** The basic concept behind Flask-Admin, is that it lets you
build complicated interfaces by grouping individual views
together in classes: Each web page you see on the frontend, represents a
method on a class that has explicitly been added to the interface.
These view classes are especially helpful when they are tied to particular
database models,
because they let you group together all of the usual
**Create, Read, Update, Delete** (CRUD) view logic into a single, self-contained
*Create, Read, Update, Delete* (CRUD) view logic into a single, self-contained
class for each of your models.
**What does it look like?** Have a look at http://examples.flask-admin.org/ to see
some examples of Flask-Admin in action, or browse through the `examples/`
directory in the `GitHub repository <https://github.com/flask-admin/flask-admin>`_.
.. toctree::
:maxdepth: 2
Index <index>
Getting Started
================
****
Initialization
--------------
-------------------
To get started, the first step, is to initialise an empty admin interface on your Flask app::
......@@ -54,7 +59,7 @@ you should see an empty page with a navigation bar on top.
Adding Model Views
----------------------
Model views allow you to add a dedicated set of admin pages for any model in your database. Do this by creating
Model views allow you to add a dedicated set of admin pages for managing any model 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::
......@@ -71,8 +76,9 @@ Straight out of the box, this gives you a set of fully featured *CRUD* views for
* A `create` view for adding new records.
* An `edit` view for updating existing records.
There are many options available for customizing the display and functionality of these builtin view.
For more details on that, see :ref:`customising-builtin-views`.
There are many options available for customizing the display and functionality of these builtin views.
For more details on that, see :ref:`customising-builtin-views`. For more details on the other
ORM backends that are available, see :ref:`database-backends`.
Adding Content to the Index Page
------------------------------------
......@@ -85,12 +91,14 @@ is that it's just an empty page with a navigation menu. To add some content to t
<p>Hello world</p>
{% endblock %}
This will override the default index template, but still give you the navigation menu. So, now you can add any content to the index page that makes sense for your app.
****
This will override the default index template, but still give you the builtin navigation menu.
So, now you can add any content to the index page, while maintaining a consistent user experience.
Authorisation & Permissions
=================================
****
When setting up an admin interface for your application, one of the first problems
you'll want to solve is how to keep unwanted users out. With Flask-Admin there
are a few different ways of approaching this.
......@@ -110,7 +118,7 @@ interface.
Rolling Your Own
--------------------------------
For a finer-grained solution, Flask-Admin lets you define access control rules
For a more flexible solution, Flask-Admin lets you define access control rules
on each of your admin view classes by simply overriding the `is_accessible` method.
How you implement the logic is up to you, but if you were to use a low-level library like
`Flask-Login <https://flask-login.readthedocs.org/>`_, then restricting access
......@@ -125,16 +133,16 @@ could be as simple as::
if not self.is_accessible():
return redirect(url_for('login', next=request.url))
Components that are not accessible to a particular user, will also not be displayed
in the menu for that user. But, you would still need to implement all of the relevant login,
Components that are not accessible to a particular user, will not be displayed
in the navigation menu for that user. But, you would still need to implement all of the relevant login,
registration and account management views yourself.
For a basic example of this, have a look at https://github.com/flask-admin/Flask-Admin/tree/master/examples/auth-flask-login.
For an example of this, have a look at https://github.com/flask-admin/Flask-Admin/tree/master/examples/auth-flask-login.
Using Flask-Security
--------------------------------
If you want to get started quicker, you could
If you want a more polished solution, you could
use `Flask-Security <https://pythonhosted.org/Flask-Security/>`_,
which is a higher-level library. It comes with lots of builtin views for doing
common things like user registration, login, email address confirmation, password resets, etc.
......@@ -149,7 +157,7 @@ of each file::
Now, you'll need to manually pass in some context variables for the Flask Admin
templates to render correctly when they're being called from the Flask-Security views.
This could look something like::
Defining a `security_context_processor` function will take care of this for you::
def security_context_processor():
return dict(
......@@ -164,13 +172,13 @@ https://github.com/flask-admin/Flask-Admin/tree/master/examples/auth.
The example only uses the builtin `register` and `login` views, but you could follow the same
approach for including the other views, like `forgot_password`, `send_confirmation`, etc.
****
.. _customising-builtin-views:
Customising Builtin Views
=================================
****
The builtin `ModelView` class is great for getting started quickly. But you'll want
to configure its functionality
to suit your particular models. This is done by setting values for the configuration
......@@ -215,10 +223,6 @@ To disable some of the basic CRUD operations, set any of these boolean parameter
can_edit = True
can_delete = True
Configuring the List View
****************************
Removing some columns from the list view is easy, just use something like::
column_exclude_list = ['password', ]
......@@ -233,11 +237,8 @@ For a faster editing experience, make some of the columns editable in the list v
column_editable_list = ['name', 'last_name']
Configuring the Create & Edit Views
************************************
To have the edit form display inside a modal window on the list page, in stead of
on the dedicated *edit* page, you can use::
Or, have the edit form display inside a modal window on the list page, in stead of
on the dedicated *edit* page::
edit_modal = True
......@@ -286,68 +287,11 @@ related models loaded via ajax, using::
}
}
Replacing Individual Form Fields
------------------------------------------
The `form_overrides` attribute allows you to replace individual fields within a form.
A common use-case for this would be to add a rich text editor, or to handle
file / image uploads that need to be tied to a field in your model.
Rich-Text Fields
**********************
To handle complicated text content, use a *WYSIWIG* text editor, like
`CKEditor <http://ckeditor.com/>`_ by subclassing some of the builtin WTForms
classes as follows::
from wtforms import TextAreaField
from wtforms.widgets import TextArea
class CKTextAreaWidget(TextArea):
def __call__(self, field, **kwargs):
if kwargs.get('class'):
kwargs['class'] += ' ckeditor'
else:
kwargs.setdefault('class', 'ckeditor')
return super(CKTextAreaWidget, self).__call__(field, **kwargs)
class CKTextAreaField(TextAreaField):
widget = CKTextAreaWidget()
class MessageAdmin(ModelView):
form_overrides = {
'body': CKTextAreaField
}
create_template = 'ckeditor.html'
edit_template = 'ckeditor.html'
For this to work, you would also need to create a template that extends the default
functionality by including the necessary CKEditor javascript on the `create` and
`edit` pages. Save this in `templates/ckeditor.html`::
{% extends 'admin/model/edit.html' %}
{% block tail %}
{{ super() }}
<script src="http://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.0.1/ckeditor.js"></script>
{% endblock %}
File & Image Fields
*******************
Flask-Admin comes with a builtin `FileUploadField` and `ImageUploadField`. To make use
of them, you'll need to specify an upload directory, and add them to the forms in question.
Image handling also requires you to have `Pillow <https://pypi.python.org/pypi/Pillow/2.8.2>`_ installed.
Have a look at the example at
https://github.com/flask-admin/Flask-Admin/tree/master/examples/forms.
If you just want to manage static files in a directory, without tying them to a database model, then
rather use the handy :ref:`File-Admin<file-admin>` plugin.
Adding Your Own Views
======================
****
Adding Your Own Views
======================
For situations where your requirements are really specific, and you struggle to meet
them with the builtin :class:`~flask_admin.model.ModelView` class: Flask-Admin makes it easy for you to
take full control and add your own views to the interface.
......@@ -406,6 +350,8 @@ For this you could override only the view in question, and all the links to it w
Working with the builtin templates
====================================
****
To take full control over the style and layout of the admin interface, you can override
all of the builtin templates. Just keep in mind that the templates will change slightly
from one version of Flask-Admin to the next, so once you start overriding them, you
......@@ -416,68 +362,16 @@ the Flask-Admin source into your project's `templates/admin/` directory.
As long as the filenames stay the same, the templates in your project directory should
automatically take precedence over the builtin ones.
If you want to keep your custom templates in some other location, then you need
to remember to reference them from the ModelView classes where you intend to
use them, for example::
class BaseModelView(ModelView):
list_template = 'base_list.html'
create_template = 'base_create.html'
edit_template = 'base_edit.html'
Have a look at the `layout` example at https://github.com/flask-admin/flask-admin/tree/master/examples/layout
to see how you can take full stylistic control over the admin interface.
...
One great advantage of building an extension on top of Flask, is the great templating engine that
comes with the package. Jinja2 allows you to use most of the Python syntax that you are used to, inside
of your templates, helping you generate either text or code in a powerful, yet flexible way.
To explore some more of what Jinja2 can offer you, head over to their documentation at
`http://jinja.pocoo.org/docs/ <http://jinja.pocoo.org/docs/>`_. But the most important features for you to
understand in order to get started with Flask-Admin are given below.
Inheritance
-----------
Templates can extend other templates. This enables you, for example, to build the standard components of
your site into a *base* template, where they are defined only once. This template can then be extended by
other templates, where more specific content may be added.
Large applications may end up having several layers of templates, starting for example with a very general HTML
structure, and then growing more and more specific at each level, until the final layer of templates define unique
pages in the application. But it needs not be very complicated, and the majority of applications will only really
need a handful of well-designed templates.
Building blocks
---------------
With Jinja2, templates are made up of *blocks* of code, which define where a child template's contents fit into the
bigger picture, as defined by the parent template.
A parent template may define any number of these code blocks, and a child template may define content for any number
of those. So, by extending an existing template, you get to just fill-in the blanks, rather than having to deal
with lots of boilerplate code that is not really relevant to the problem at hand.
Power & Flexibility
-------------------
When a block is defined in a parent template, it can already be given some content, ensuring that something
will be rendered in that place, even if a child template chooses to ignore that block completely.
If content is defined in a child template, you have the option of also rendering the code that the parent template
may have defined in that block by calling::
{{ super() }}
See :ref:`extending-builtin-templates`.
To explore some more of what Jinja2 can offer you, head over to the
`Jinja2 docs <http://jinja.pocoo.org/docs/>`_.
anywhere inside that block. But the default behaviour is to simply override the block entirely.
Since these template blocks are defined by name, you have a lot of freedom in how you decide to arrange / nest them
in your code.
Jinja2 & Flask Admin
--------------------
Available Template Blocks
----------------------------
Flask-Admin defines one *base* template at `admin/master.html` that all the other admin templates are derived
from. This template is a proxy which points to `admin/base.html`, which defines
......@@ -500,43 +394,20 @@ body Content (that's where your view will be displayed)
tail Empty area below content
============== ========================================================================
Adding an Index Page
--------------------
You'll notice that the 'Home' page that is created by Flask-Admin at `/admin` is largely empty. By default, the
only content on the page is a set of controls for navigating to the views that you have defined. You can change this by
creating a template at `admin/index.html` in your `templates` directory.
Working with your Models
------------------------
By default, Flask-Admin uses three pre-defined templates for displaying your models in the admin-interface:
* `admin/model/list.html`
* `admin/model/create.html`
* `admin/model/edit.html`
All three of these extend the `admin/master.html` template, and you can override them by defining your own templates,
with the same path relative to your `templates` folder.
You could also choose to extend these templates, rather than overriding them. In this case you will need to
point your classes at your own templates, rather than letting them use the defaults. For example, your own template
for the *edit* views could be defined in `templates/my_edit_template.html` to look something like::
{% extends 'admin/model/edit.html' %}
{% block tail %}
{{ super() }}
...
{% endblock %}
And your classes could be made to use this template by setting the appropriate class property::
class MyModelView(ModelView):
edit_template = 'my_edit_template.html'
The three available properties are simply called `list_template`, `create_template` and `edit_template`.
In addition to all of the blocks that are inherited from `admin/master.html`, the `admin/model/list.html` template
also contains the following blocks:
======================= ============================================
Block Name Description
======================= ============================================
model_menu_bar Menu bar
model_list_table Table container
list_header Table header row
list_row_actions_header Actions header
list_row Single row
list_row_actions Row action cell with edit/remove/etc buttons
empty_list_message Message that will be displayed if there are no models found
======================= ============================================
Environment variables
---------------------
......@@ -566,78 +437,8 @@ constructor::
admin = Admin(app, base_template='my_master.html')
In addition to all of the blocks that are inherited from `admin/master.html`, the `admin/model/list.html` template
also contains the following blocks:
======================= ============================================
Block Name Description
======================= ============================================
model_menu_bar Menu bar
model_list_table Table container
list_header Table header row
list_row_actions_header Actions header
list_row Single row
list_row_actions Row action cell with edit/remove/etc buttons
empty_list_message Message that will be displayed if there are no models found
======================= ============================================
****
Usage Tips
============
General tips
------------
1. A reasonably obvious, but very useful, pattern is to wrap any shared functionality that your different admin views
might need into a base class that they can all inherit from (to help you keep things
`DRY <http://en.wikipedia.org/wiki/Don't_repeat_yourself>`_).
For example, rather than manually checking user permissions in each of your admin views, you can implement a
base class such as ::
class MyView(BaseView):
def is_accessible(self):
return login.current_user.is_authenticated()
and every view that inherits from this, will have the permission checking done automatically. The important thing
to notice, is that your base class needs to inherit from a built-in Flask-Admin view.
2. You can override a default template either by passing the path to your own template in to the relevant `ModelView`
property (either `list_template`, `create_template` or `edit_template`) or by putting your own customized
version of a default template into your `templates/admin/` directory.
3. To customize the overall look and feel of the default model forms, you have two options: Either, you could
override the default create/edit templates. Or, alternatively, you could make use of the form rendering rules
(:mod:`flask_admin.form.rules`) that were introduced in version 1.0.7.
4. To simplify the management of file uploads, Flask-Admin comes with a dedicated tool, for which you can find
documentation at: :mod:`flask_admin.form.upload`.
5. If you don't want to the use the built-in Flask-Admin form scaffolding logic, you are free to roll your own
by simply overriding :meth:`~flask_admin.model.base.scaffold_form`. For example, if you use
`WTForms-Alchemy <https://github.com/kvesteri/wtforms-alchemy>`_, you could put your form generation code
into a `scaffold_form` method in your `ModelView` class.
SQLAlchemy
----------
1. If the `synonym_property` does not return a SQLAlchemy field, then Flask-Admin won't be able to figure out what to
do with it, so it won't generate a form field. In this case, you would need to manually contribute your own field::
class MyView(ModelView):
def scaffold_form(self):
form_class = super(UserView, self).scaffold_form()
form_class.extra = TextField('Extra')
return form_class
MongoEngine
-----------
1. Flask-Admin supports GridFS-backed image- and file uploads, done through WTForms fields. Documentation can be found
at :mod:`flask_admin.contrib.mongoengine.fields`.
Generating URLs
------------------
......@@ -684,15 +485,11 @@ If you want to generate a URL for a particular view method from outside, the fol
url_for('user.edit_view', id=1, url=url_for('user.index_view'))
Adding a Redis console
--------------------------
****
Further Reading
==================
****
.. toctree::
:maxdepth: 2
......
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