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

Final big edit for index page.

parent e2371194
......@@ -35,7 +35,49 @@ And your classes could be made to use this template by setting the appropriate c
The three available properties are simply called `list_template`, `create_template` and `edit_template`.
If you want to use your own base template, then pass the name of the template to
the admin constructor during initialization::
admin = Admin(app, base_template='my_master.html')
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
the following blocks:
============== ========================================================================
Block Name Description
============== ========================================================================
head_meta Page metadata in the header
title Page title
head_css Various CSS includes in the header
head Empty block in HTML head, in case you want to put something there
page_body Page layout
brand Logo in the menu bar
main_menu Main menu
menu_links Links menu
access_control Section to the right of the menu (can be used to add login/logout buttons)
messages Alerts and various messages
body Content (that's where your view will be displayed)
tail Empty area below content
============== ========================================================================
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
======================= ============================================
Replacing Individual Form Fields
------------------------------------------
......@@ -695,6 +737,6 @@ Usage Tips
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::
admin = Admin(name='My App', template_mode='bootstrap3')
admin = Admin(name='microblog', template_mode='bootstrap3')
# Add views here
admin.init_app(app)
\ No newline at end of file
......@@ -21,16 +21,10 @@ because they let you group together all of the usual
*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
**What does it look like?** At http://examples.flask-admin.org/ you can 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
================
......@@ -39,14 +33,14 @@ Getting Started
Initialization
-------------------
To get started, the first step, is to initialise an empty admin interface on your Flask app::
The first step, is to initialise an empty admin interface on your Flask app::
from flask import Flask
from flask_admin import Admin
app = Flask(__name__)
admin = Admin(app, name='My App', template_mode='bootstrap3')
admin = Admin(app, name='microblog', template_mode='bootstrap3')
# Add administrative views here
app.run()
......@@ -67,8 +61,9 @@ is the SQLAlchemy backend, which you can use as follows::
# Flask and Flask-SQLAlchemy initialization here
admin = Admin(app)
admin = Admin(app, name='microblog', template_mode='bootstrap3')
admin.add_view(ModelView(User, db.session))
admin.add_view(ModelView(Post, db.session))
Straight out of the box, this gives you a set of fully featured *CRUD* views for your model:
......@@ -124,20 +119,23 @@ How you implement the logic is up to you, but if you were to use a low-level lib
`Flask-Login <https://flask-login.readthedocs.org/>`_, then restricting access
could be as simple as::
class BaseModelView(sqla.ModelView):
class MicroBlogModelView(sqla.ModelView):
def is_accessible(self):
return login.current_user.is_authenticated()
def _handle_view(self, name, **kwargs):
# redirect to login page if user doesn't have access
if not self.is_accessible():
return redirect(url_for('login', next=request.url))
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,
In the navigation menu, components that are not accessible to a particular user will not be displayed
for that user. For an example of using Flask-Login with Flask-Admin, have a look
at https://github.com/flask-admin/Flask-Admin/tree/master/examples/auth-flask-login.
The main drawback is that you still need to implement all of the relevant login,
registration and account management views yourself.
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
--------------------------------
......@@ -191,12 +189,12 @@ subclass when adding your models to the interface::
# Flask and Flask-SQLAlchemy initialization here
class BaseModelView(ModelView):
class MicroBlogModelView(ModelView):
can_delete = False # disable model deletion
page_size = 50 # the number of entries to display on the list view
admin.add_view(BaseModelView(User, db.session))
admin.add_view(BaseModelView(Post, db.session))
admin.add_view(MicroBlogModelView(User, db.session))
admin.add_view(MicroBlogModelView(Post, db.session))
Or, in much the same way, you can specify options for a single model at a time::
......@@ -217,32 +215,33 @@ For a complete list of the attributes that are defined, have a look at the
API documentation for :meth:`~flask_admin.model.BaseModelView`. Here follows
some of the most commonly used ones:
To disable some of the basic CRUD operations, set any of these boolean parameters::
To **disable some of the CRUD operations**, set any of these boolean parameters::
can_create = True
can_edit = True
can_delete = True
can_create = False
can_edit = False
can_delete = False
Removing some columns from the list view is easy, just use something like::
**Removing columns** from the list view is easy, just pass a list of column names for
the *column_excludes_list* parameter::
column_exclude_list = ['password', ]
To make some of your columns searchable, or to use them for filtering, specify
To **make columns searchable**, or to use them for filtering, specify
a list of column names::
column_searchable_list = ['name', 'email']
column_filters = ['country', ]
For a faster editing experience, make some of the columns editable in the list view::
For a faster editing experience, enable **inline editing** in the list view::
column_editable_list = ['name', 'last_name']
Or, have the edit form display inside a modal window on the list page, in stead of
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
You can restrict the possible values for a text-field by specifying a list of choices::
You can restrict the possible values for a text-field by specifying a list of **select choices**::
form_choices = {
'title': [
......@@ -254,11 +253,11 @@ You can restrict the possible values for a text-field by specifying a list of ch
]
}
To remove some fields from the create and edit forms::
To **remove fields** from the create and edit forms::
form_excluded_columns = ['last_name', 'email']
To specify arguments to the WTForms fields when they are being rendered::
To specify **WTForms field arguments**::
form_args = {
'name': {
......@@ -267,7 +266,7 @@ To specify arguments to the WTForms fields when they are being rendered::
}
}
And, to go one level deeper, you can specify arguments to the widgets used to
Or, to specify arguments to the **WTForms widgets** used to
render those fields::
form_widget_args = {
......@@ -277,8 +276,7 @@ render those fields::
}
}
To speed up page loading when you have forms with foreign keys, have those
related models loaded via ajax, using::
When your forms contain foreign keys, have those **related models loaded via ajax**, using::
form_ajax_refs = {
'user': {
......@@ -287,21 +285,26 @@ related models loaded via ajax, using::
}
}
TODO: Handling Foreign Key relations inline
To **manage related models inline**::
inline_models = ['post', ]
These inline forms can be customised. Have a look at the API documentation for
:meth:`~flask_admin.contrib.sqla.ModelView.inline_models`.
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
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.
Standalone Views
------------------
To add a set of standalone views, that are not tied to any particular model, you can extend the
:class:`~flask_admin.base.BaseView` class, and define your own view methods on it. For
A set of standalone views, that are not tied to any particular model, can be added by extending the
:class:`~flask_admin.base.BaseView` class, and defining your own view methods on it. For
example, to add a page that displays some analytics data from a 3rd-party API::
from flask_admin import BaseView, expose
......@@ -311,11 +314,12 @@ example, to add a page that displays some analytics data from a 3rd-party API::
def index(self):
return self.render('analytics_index.html')
admin.add_view(CustomView(name='Analytics'))
admin.add_view(CustomView(name='Analytics', endpoint='analytics'))
This will add a link to the navbar, from where your view can be accessed. Notice that
it is served at '/', the root URL. This is a restriction on standalone views: at the very minimum, each view class needs
at least one method, that serves a view at the root URL.
it is served at '/', the root URL. This is a restriction on standalone views: at
the very minimum, each view class needs
at least one method to serve a view at its root.
The `analytics_index.html` template for the example above, could look something like::
......@@ -346,14 +350,13 @@ For this you could override only the view in question, and all the links to it w
return self.render('create_user.html')
Working with the builtin templates
====================================
****
Flask-Admin uses the `Jinja2 <http://jinja.pocoo.org/docs/>`_ templating engine.
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
......@@ -367,49 +370,8 @@ automatically take precedence over the builtin ones.
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.
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/>`_.
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
the following blocks:
============== ========================================================================
Block Name Description
============== ========================================================================
head_meta Page metadata in the header
title Page title
head_css Various CSS includes in the header
head Empty block in HTML head, in case you want to put something there
page_body Page layout
brand Logo in the menu bar
main_menu Main menu
menu_links Links menu
access_control Section to the right of the menu (can be used to add login/logout buttons)
messages Alerts and various messages
body Content (that's where your view will be displayed)
tail Empty area below content
============== ========================================================================
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
======================= ============================================
See :ref:`extending-builtin-templates` for an alternative approach, that could make
life easier for you when upgrading to future versions of Flask-Admin.
Environment variables
---------------------
......@@ -427,25 +389,12 @@ _ngettext Babel ngettext
h Helpers from :mod:`~flask_admin.helpers` module
==================== ================================
Customizing templates
---------------------
As noted earlier, you can override any default Flask-Admin template by creating your own template with same name and
relative path inside your own `templates` directory.
You can also override the master template, but then you need to pass your own template name to the `Admin`
constructor::
admin = Admin(app, base_template='my_master.html')
****
Generating URLs
------------------
Internally, view classes work on top of Flask blueprints, so you can use *url_for* with a dot
prefix to get the URL for a local view::
To get the URL for a specific view, use *url_for* with a dot prefix::
from flask import url_for
......@@ -453,39 +402,23 @@ prefix to get the URL for a local view::
@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 a URL for a particular view method from outside, the following rules apply:
1. You can override the endpoint name by passing *endpoint* parameter to the view class constructor::
admin = Admin(app)
admin.add_view(MyView(endpoint='testadmin'))
user_list_url = url_for('user.index_view')
return self.render('index.html', user_list_url=user_list_url)
In this case, you can generate links by concatenating the view method name with an endpoint::
A specific record can also be referenced with::
url_for('testadmin.index')
2. If you don't override the endpoint name, the lower-case class name can be used for generating URLs, like in::
url_for('myview.index')
3. For model-based views the rules differ - the model class name should be used if an endpoint name is not provided. The ModelView also has these endpoints by default: *.index_view*, *.create_view*, and *.edit_view*. So, the following urls can be generated for a model named "User"::
# Edit View for record #1 (redirect back to index_view)
url_for('user.edit_view', id=1, url=url_for('user.index_view'))
# List View
url_for('user.index_view')
When referencing ModelView instances, use the lowercase name of the model as the
prefix when calling *url_for*. Other views can be referenced by specifying a
unique endpoint for each, and using that as the prefix. So, to referece::
# Create View (redirect back to index_view)
url_for('user.create_view', url=url_for('user.index_view'))
admin.add_view(CustomView(name='Analytics', endpoint='analytics'))
# Edit View for record #1 (redirect back to index_view)
url_for('user.edit_view', id=1, url=url_for('user.index_view'))
Use::
url_for('analytics.index')
Further Reading
==================
......
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