Commit 5ad1fd96 authored by Serge S. Koval's avatar Serge S. Koval

Merge branch 'master' of github.com:/mrjoes/flask-admin

parents 8b30967e d6b827f4
......@@ -13,7 +13,6 @@ flask_admin/tests/tmp
dist/*
make.bat
venv
*.sqlite
*.sublime-*
.coverage
__pycache__
......
......@@ -7,9 +7,9 @@ Flask-Admin
Introduction
------------
Flask-Admin is a batteries-included, simple-to-use Flask extension that lets you add admin interfaces to Flask
applications. It is inspired by the *django-admin* package, but implemented in such a way that the developer has total control
of the look, feel and functionality of the resulting application.
Flask-Admin is a batteries-included, simple-to-use `Flask <http://flask.pocoo.org/>`_ extension that lets you
add admin interfaces to Flask applications. It is inspired by the *django-admin* package, but implemented in such
a way that the developer has total control of the look, feel and functionality of the resulting application.
Out-of-the-box, Flask-Admin plays nicely with various ORM's, including
......@@ -23,8 +23,6 @@ Out-of-the-box, Flask-Admin plays nicely with various ORM's, including
It also boasts a simple file management interface and a `redis client <http://redis.io/>`_ console.
Several usage examples are included in the */examples* folder. Feel free to add your own examples, or improve some of the existing ones, and submit them as a *pull-request*.
The biggest feature of Flask-Admin is flexibility. It aims to provide a set of simple tools that can be used for
building admin interfaces of any complexity. So, to start off with you can create a very simple application in no time,
with auto-generated CRUD-views for each of your models. But then you can go further and customize those views & forms
......@@ -32,11 +30,32 @@ as the need arises.
Flask-Admin is an active project, well-tested and production ready.
Examples
--------
Several usage examples are included in the */examples* folder. Please feel free to add your own examples, or improve
on some of the existing ones, and then submit them via GitHub as a *pull-request*.
You can see some of these examples in action at `http://examples.flask-admin.org <http://examples.flask-admin.org/>`_.
To run one of the examples in your local environment, simply::
cd flask-admin
python examples/simple/simple.py
Documentation
-------------
Flask-Admin is extensively documented, you can find all of the documentation at `http://readthedocs.org/docs/flask-admin <http://readthedocs.org/docs/flask-admin>`_.
The docs are auto-generated for the *.rst* files in the */doc* folder. So if you come across any errors, or think of anything that should be included, then please make the changes and submit them as a *pull-request*.
The docs are auto-generated from the *.rst* files in the */doc* folder. So if you come across any errors, or
if you think of anything else that should be included, then please make the changes and submit them as a *pull-request*.
To build the docs in your local environment::
sudo pip install sphinx
cd flask-admin
sudo make html
Or, if you want to preview any *.rst* snippets that you may want to contribute, go to `http://rst.ninjs.org/ <http://rst.ninjs.org/>`_.
Installation
------------
......@@ -63,8 +82,9 @@ and then::
cd flask-admin
nosetests
You should see output such as::
You should see output similar to::
...
----------------------------------------------------------------------
Ran 41 tests in 2.092s
......
......@@ -4,7 +4,7 @@ stylesheet = flasky.css
pygments_style = flask_theme_support.FlaskyStyle
[options]
index_logo =
index_logo_height = 120px
index_logo = 'flask-admin.png'
index_logo_height = 140px
touch_icon =
github_fork = 'mrjoes/flask-admin'
......@@ -4,7 +4,7 @@ Changelog
1.0.7
-----
Full change log and feature walkthrough can be found `here <http://mrjoes.github.io/2013/03/22/flask-admin-107.html>`_.
Full change log and feature walkthrough can be found `here <http://mrjoes.github.io/2013/10/21/flask-admin-107.html>`_.
Highlights:
......
......@@ -115,12 +115,12 @@ html_theme_path = ['_themes']
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
html_logo = '_static/logo.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
html_favicon = 'favicon.ico'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
......@@ -129,7 +129,7 @@ html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
......
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 four different backends for you to choose
from, depending on which database you would like to use for your application.
.. toctree::
:maxdepth: 2
......@@ -8,3 +12,17 @@ Database backends
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 <http://www.sqlalchemy.org/>`_. 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're looking for something simpler, or your data models are reasonably self-contained, then
`MongoEngine <http://mongoengine.org/>`_ could be a better option. It is a python wrapper around the popular
*NoSQL* database called `MongoDB <http://www.mongodb.org/>`_.
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`.
This diff is collapsed.
Form rendering rules
--------------------
====================
Before version 1.0.7, all model backends were rendering the creation and editing forms
using the special Jinja2 macro, which was looping over WTForms form object fields and displaying
them one by one.
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 so called form rendering rules.
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.
Idea is pretty simple: instead of having non-configurable macro that renders the form,
have a set of rules that tell Flask-Admin how form should be rendered. As an extension
of the idea, rules can output HTML, call Jinja2 macros, render fields and so on.
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 form rendering away from the form definition. And it
no longer matters what is sequence of the fields in the form.
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 yur form fields are defined.
Getting started
---------------
To start using form rendering rules, you need to put list of form field names into `form_create_rules`
property of your administrative view::
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 string as a value in `form_create_rules`, it automatically assumes that it is
form field reference and created :class:`flask.ext.admin.form.rules.Field` class instance.
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.ext.admin.form.rules.Field` class instance for that field.
Lets say we want to display 'Foobar' text between `email` and `first_name` fields. This can be accomplished by
using :class:`flask.ext.admin.form.rules.Text` class::
Lets say we want to display some text between the `email` and `first_name` fields. This can be accomplished by
using the :class:`flask.ext.admin.form.rules.Text` class::
from flask.ext.admin.form import rules
class RuleView(sqla.ModelView):
form_create_rules = ('email', rules.Text('Foobar'), 'first_name', 'last_name')
Flask-Admin comes with few built-in rules that can be found in :mod:`flask.ext.admin.form.rules` module:
Built-in rules
--------------
Flask-Admin comes with few built-in rules that can be found in the :mod:`flask.ext.admin.form.rules` module:
======================================================= ========================================================
Form Rendering Rule Description
======================================================= ========================================================
:class:`flask.ext.admin.form.rules.BaseRule` All rules derive from this class
:class:`flask.ext.admin.form.rules.NestedRule` Allows rule nesting, useful for HTML containers
......@@ -50,5 +56,8 @@ Flask-Admin comes with few built-in rules that can be found in :mod:`flask.ext.a
:class:`flask.ext.admin.form.rules.FieldSet` Renders form header and child rules
======================================================= ========================================================
Further reading
---------------
For additional documentation, check :mod:`flask.ext.admin.form.rules` module source code (it is quite short) and
look at the `forms` example.
look at the `forms example <https://github.com/mrjoes/flask-admin/tree/master/examples/forms>`_ on GitHub.
Flask-Admin
===========
Flask-Admin is simple and extensible administrative interface framework for `Flask <http://flask.pocoo.org/>`_.
Flask-Admin is a batteries-included, simple-to-use `Flask <http://flask.pocoo.org/>`_ extension that lets you
add admin interfaces to Flask applications. It is inspired by the *django-admin* package, but implemented in such
a way that the developer has total control of the look, feel and functionality of the resulting application.
You can see some examples of how Flask-Admin can be used at `http://examples.flask-admin.org <http://examples.flask-admin.org/>`_.
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/mrjoes/flask-admin>`_ to find out how you can contribute to the project.
.. toctree::
:maxdepth: 2
......@@ -12,8 +19,8 @@ Flask-Admin is simple and extensible administrative interface framework for `Fla
localization
tips
db
form_rules
model_guidelines
form_rules
api/index
changelog
renamed_columns
......
Localization
============
Flask-Admin uses the `Flask-BabelEx <http://github.com/mrjoes/flask-babelex/>`_ package to handle translations.
Flask-BabelEx is a fork of Flask-Babel with following features:
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/mrjoes/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. Much more configurable
3. It aims to be more configurable than Flask-Babel
If Flask-Admin can not import Flask-BabelEx, it disables localization support completely.
Currently *Flask-BabelEx* is the only supported way of enabling localization support in Flask-Admin.
How to enable localization
--------------------------
1. Initialize Flask-BabelEx by creating instance of `Babel` class::
1. Install Flask-BabelEx::
pip install flask-babelex
2. Initialize Flask-BabelEx by creating instance of `Babel` class::
from flask import app
from flask.ext.babelex import Babel
......@@ -22,7 +26,7 @@ How to enable localization
app = Flask(__name__)
babel = Babel(app)
2. Create locale selector function::
3. Create a locale selector function::
@babel.localeselector
def get_locale():
......@@ -30,7 +34,9 @@ How to enable localization
# user profile, cookie, session, etc.
return 'en'
3. Initialize Flask-Admin as usual.
4. Initialize Flask-Admin as usual.
You can check `babel` example to see localization in action. To change locale, add *?en=<locale name>* to the URL. For example, URL
can look like: `http://localhost:5000/admin/userview/?lang=fr <http://localhost:5000/admin/userview/?lang=fr>`_.
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>`_.
......@@ -165,7 +165,6 @@ have access to the view in question::
def is_accessible(self):
return login.current_user.is_authenticated()
You can also implement policy-based security, conditionally allowing or disallowing access to parts of the
administrative interface. If a user does not have access to a particular view, the menu item won't be visible.
......
Working with templates
======================
Flask-Admin is built on top of standard Flask template management functionality.
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.
If you're not familiar with Jinja2 templates, take a look `here <http://jinja.pocoo.org/docs/templates/>`_. Short summary:
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.
1. You can derive from template;
2. You can override template block(s);
3. When you override template block, you can render or not render parent block;
4. It does not matter how blocks are nested - you override them by name.
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.
Flask Core
----------
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.
All Flask-Admin templates should derive from `admin/master.html`.
Building blocks
---------------
`admin/master.html` is a proxy which points to `admin/base.html`. It contains following 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() }}
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
--------------------
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
......@@ -33,33 +71,52 @@ body Content (that's where your view will be displayed)
tail Empty area below content
============== ========================================================================
`admin/index.html` will be used display default `Home` admin page. By default it is empty.
Adding an Index Page
--------------------
Models
------
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.
There are 3 main templates that are used to display models:
Working with your Models
------------------------
`admin/model/list.html` is list view template and contains following blocks:
By default, Flask-Admin uses three pre-defined templates for displaying your models in the admin-interface:
======================= ============================================
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
======================= ============================================
* `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`.
`admin/model/create.html` and `admin/model/edit.html` are used to display model creation editing forms respectively. They don't contain any custom
blocks and if you want to change something, you can do it using any of the blocks found in `admin/master.html`.
Environment variables
---------------------
There are few variables and methods that are always accessible in administrative templates:
While working in any of the templates that extend `admin/master.html`, you have access to a small number of
environment variables:
==================== ================================
Variable Name Description
==================== ================================
admin_view Current administrative view
admin_base_template Base template name
......@@ -72,10 +129,25 @@ h Helpers from :mod:`~flask.ext.admin.helpers` module
Customizing templates
---------------------
You can override any used template in your Flask application by creating template with same name and relative path in your main `templates` directory.
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.
If you need to override master template, you can pass template name to the `Admin` constructor::
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')
For model views, use `list_template`, `create_template` and `edit_template` properties to use non-default 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
======================= ============================================
\ No newline at end of file
......@@ -4,38 +4,42 @@ Usage Tips
General tips
------------
1. Whenever your administrative views share common functionality such as authentication,
form validation, make use of read-only views and so on - create your own base class which
inherits from proper Flask-Admin view class.
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, if you need to check user permissions for every call, don't implement
`is_accessible` in every administrative view. Create your own base class, implement
`is_accessible` there and use this class for all your views.
For example, rather than manually checking user permissions in each of your admin views, you can implement a
base class such as ::
2. You can override used templates either by using `ModelView` properties (such as
`list_template`, `create_template`, `edit_template`) or
putting customized version of the template into your `templates/admin/` directory
class MyView(BaseView):
def is_accessible(self):
return login.current_user.is_authenticated()
3. If you need to customize look and feel of model forms, there are two options:
- Override create/edit template
- Use new :mod:`flask.ext.admin.form.rules` form rendering rules
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.
4. Flask-Admin has that manage file/image uploads and store result in model field. You can
find documentation here :mod:`flask.ext.admin.form.upload`.
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.
5. If you don't want to use Flask-Admin form scaffolding logic, you can override
:meth:`~flask.ext.admin.model.base.scaffold_form` and put your own form creation
logic there. For example, if you use `WTForms-Alchemy <https://github.com/kvesteri/wtforms-alchemy>`_, all you have to do
is to put appropriate form generation code into your `ModelView` class into the
`scaffold_form` method.
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.ext.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.ext.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.ext.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 `synonym_property` does not return SQLAlchemy field, Flask-Admin
won't be able to figure out what to do with it and won't generate form
field. In this case, you need to manually contribute field::
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):
......@@ -46,5 +50,5 @@ SQLAlchemy
MongoEngine
-----------
1. Flask-Admin supports GridFS backed image and file uploads. Done through
WTForms fields and documentation can be found here :mod:`flask.ext.admin.contrib.mongoengine.fields`.
1. Flask-Admin supports GridFS-backed image- and file uploads, done through WTForms fields. Documentation can be found
at :mod:`flask.ext.admin.contrib.mongoengine.fields`.
......@@ -76,7 +76,7 @@ class RegistrationForm(form.Form):
# Initialize flask-login
def init_login():
login_manager = login.LoginManager()
login_manager.setup_app(app)
login_manager.init_app(app)
# Create user loader function
@login_manager.user_loader
......
......@@ -11,7 +11,7 @@ app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///dummy.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sample_db.sqlite'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
......@@ -53,13 +53,14 @@ def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
if __name__ == '__main__':
# Create admin with custom base template
admin = admin.Admin(app, base_template='layout.html')
# Create admin with custom base template
admin = admin.Admin(app, base_template='layout.html')
# Add views
admin.add_view(UserAdmin(User, db.session))
admin.add_view(CustomView(Page, db.session))
# Add views
admin.add_view(UserAdmin(User, db.session))
admin.add_view(CustomView(Page, db.session))
if __name__ == '__main__':
# Create DB
db.create_all()
......
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="row-fluid">
<h1>Flask-Admin example</h1>
<p class="lead">
Customize the layout
</p>
<p>
This example shows how you can customize the look & feel of the admin interface.
</p>
<p>
This is done by overriding some of the built-in templates.
</p>
<a class="btn btn-primary" href="/"><i class="icon-arrow-left icon-white"></i> Back</a>
</div>
{% endblock body %}
\ No newline at end of file
......@@ -3,6 +3,11 @@ from flask.ext.admin import Admin
app = Flask(__name__)
app.debug = True
admin = Admin(app)
app.run(debug=True)
if __name__ == '__main__':
# Start app
app.run(debug=True)
......@@ -8,8 +8,12 @@ class MyView(BaseView):
return self.render('index.html')
app = Flask(__name__)
app.debug = True
admin = Admin(app)
admin.add_view(MyView(name='Hello'))
app.run(debug=True)
if __name__ == '__main__':
# Start app
app.run()
from flask import Flask
from flask.ext.admin import Admin, BaseView, expose
class MyView(BaseView):
@expose('/')
def index(self):
return self.render('index.html')
app = Flask(__name__)
app.debug = True
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(debug=True)
if __name__ == '__main__':
# Start app
app.run()
......@@ -22,20 +22,20 @@ class AnotherAdminView(admin.BaseView):
# Create flask app
app = Flask(__name__, template_folder='templates')
app.debug = True
# Flask views
@app.route('/')
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
# Create admin interface
admin = admin.Admin()
admin.add_view(MyAdminView(category='Test'))
admin.add_view(AnotherAdminView(category='Test'))
admin.init_app(app)
if __name__ == '__main__':
# Create admin interface
admin = admin.Admin()
admin.add_view(MyAdminView(category='Test'))
admin.add_view(AnotherAdminView(category='Test'))
admin.init_app(app)
# Start app
app.run(debug=True)
app.run()
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="row-fluid">
<h1>Flask-Admin example</h1>
<p class="lead">
Simple admin views, not related to models.
</p>
<p>
This example shows how to add your own views to the admin interface. The views do not have to be associated
to any of your models, and you can fill them with whatever content you want.
</p>
<p>
By adding custom views to the admin interface, they become accessible through the <em>navbar</em> at the top.
</p>
<a class="btn btn-primary" href="/"><i class="icon-arrow-left icon-white"></i> Back</a>
</div>
{% endblock body %}
\ No newline at end of file
......@@ -13,7 +13,7 @@ app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sample_db_2.sqlite'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
......@@ -22,6 +22,7 @@ db = SQLAlchemy(app)
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
class Car(db.Model):
__tablename__ = 'cars'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
......@@ -30,6 +31,7 @@ class Car(db.Model):
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)
......@@ -37,19 +39,22 @@ class Tyre(db.Model):
car = db.relationship('Car', backref='tyres')
desc = db.Column(db.String(50))
class CarAdmin(sqla.ModelView):
column_display_pk = True
form_columns = ['id', 'desc']
class TyreAdmin(sqla.ModelView):
column_display_pk = True
form_columns = ['car', 'tyre_id', 'desc']
# Create admin
admin = admin.Admin(app, 'Simple Models')
admin.add_view(CarAdmin(Car, db.session))
admin.add_view(TyreAdmin(Tyre, db.session))
if __name__ == '__main__':
# Create admin
admin = admin.Admin(app, 'Simple Models')
admin.add_view(CarAdmin(Car, db.session))
admin.add_view(TyreAdmin(Tyre, db.session))
# Create DB
db.create_all()
......
......@@ -16,7 +16,7 @@ app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sample_db.sqlite'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
......@@ -139,15 +139,16 @@ class TreeView(sqla.ModelView):
inline_models = (Tree,)
# Create admin
admin = admin.Admin(app, 'Simple Models')
# Add views
admin.add_view(UserAdmin(User, db.session))
admin.add_view(sqla.ModelView(Tag, db.session))
admin.add_view(PostAdmin(db.session))
admin.add_view(TreeView(Tree, db.session))
if __name__ == '__main__':
# Create admin
admin = admin.Admin(app, 'Simple Models')
# Add views
admin.add_view(UserAdmin(User, db.session))
admin.add_view(sqla.ModelView(Tag, db.session))
admin.add_view(PostAdmin(db.session))
admin.add_view(TreeView(Tree, db.session))
# Create DB
db.create_all()
......
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="row-fluid">
<h1>Flask-Admin example</h1>
<p class="lead">
Basic SQLAlchemy model views.
</p>
<p>
This example shows how to add basic CRUD-views for your SQLAlchemy models.
</p>
<p>
The views are generated automatically, but it is perfectly possible to customize them to suit your needs.
</p>
<a class="btn btn-primary" href="/"><i class="icon-arrow-left icon-white"></i> Back</a>
</div>
{% endblock body %}
\ No newline at end of file
......@@ -6,6 +6,13 @@ from wtforms.fields.core import _unset_value
from . import widgets
def is_empty(file_object):
file_object.seek(0)
first_char = file_object.read(1)
file_object.seek(0)
return not bool(first_char)
class ModelFormField(fields.FormField):
"""
Customized ModelFormField for MongoEngine EmbeddedDocuments.
......@@ -54,7 +61,7 @@ class MongoFileField(fields.FileField):
field.delete()
return
if isinstance(self.data, FileStorage):
if isinstance(self.data, FileStorage) and not is_empty(self.data.stream):
if not field.grid_id:
func = field.put
else:
......
......@@ -545,7 +545,7 @@ class InlineModelConverter(InlineModelConverterBase):
reverse_prop = None
for prop in target_mapper.iterate_properties:
if hasattr(prop, 'direction') and prop.direction.name == 'MANYTOONE':
if hasattr(prop, 'direction'):
if issubclass(model, prop.mapper.class_):
reverse_prop = prop
break
......@@ -556,7 +556,7 @@ class InlineModelConverter(InlineModelConverterBase):
forward_prop = None
for prop in mapper.iterate_properties:
if hasattr(prop, 'direction') and prop.direction.name == 'ONETOMANY':
if hasattr(prop, 'direction'):
if prop.mapper.class_ == target_mapper.class_:
forward_prop = prop
break
......
......@@ -76,7 +76,7 @@ class InlineFieldList(FieldList):
_fake = type(str('_fake'), (object, ), {})
output = []
for field, data in itertools.izip(self.entries, candidates):
for field, data in zip(self.entries, candidates):
if not self.should_delete(field):
fake_obj = _fake()
fake_obj.data = data
......
......@@ -78,7 +78,7 @@
this.applyStyle = function($el, name) {
// Process converters first
for (var conv in fieldConverters) {
var fildConv = fieldConverters[conv];
var fieldConv = fieldConverters[conv];
if (fieldConv($el, name))
return true;
......@@ -185,10 +185,20 @@
self.applyStyle($el, $el.attr('data-role'));
});
};
/**
* Add a field converter for customizing styles
*
* @method addFieldConverter
* @param {converter} function($el, name)
*/
this.addFieldConverter = function(converter) {
fieldConverters.push(converter);
};
};
// Add live event handler
$('.fa-remove-field').live('click', function(e) {
// Add on event handler
$('body').on('click', '.fa-remove-field' , function(e) {
e.preventDefault();
var form = $(this).closest('.fa-inline-field');
......
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