Commit cfcb906d authored by Serge S. Koval's avatar Serge S. Koval

Merged with current master

parents 402b56ea 0dbca4d4
......@@ -3,6 +3,7 @@ python:
- "2.6"
- "2.7"
- "3.3"
- "3.4"
env:
- WTFORMS_VERSION=1
......@@ -18,7 +19,7 @@ before_script:
install:
- pip install "wtforms<$WTFORMS_VERSION.99"
- pip install -r dev-requirements.txt
- pip install -r requirements-dev.txt
script: nosetests flask_admin/tests
# flask-admin
Project was moved into its own organization: https://github.com/flask-admin
Please update your references.
Flask-Admin
===========
.. image:: https://travis-ci.org/mrjoes/flask-admin.png?branch=master
:target: https://travis-ci.org/mrjoes/flask-admin
The project was recently moved into its own organization. Please update your
references to *git@github.com:flask-admin/flask-admin.git*.
.. image:: https://d322cqt584bo4o.cloudfront.net/flask-admin/localized.png
:target: https://crowdin.com/project/flask-admin
.. image:: https://travis-ci.org/flask-admin/flask-admin.png?branch=master
:target: https://travis-ci.org/flask-admin/flask-admin
Introduction
------------
......@@ -36,30 +42,24 @@ Several usage examples are included in the */examples* folder. Please feel free
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 that same page in your local environment, simply::
cd flask-admin
python examples/runserver.py
Alternatively, you can run the examples one at a time, with something like::
To run the examples on your local environment, one at a time, do something like::
cd flask-admin
python examples/simple/simple.py
python examples/simple/app.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>`_.
Flask-Admin is extensively documented, you can find all of the documentation at `http://flask-admin.readthedocs.org/en/latest/ <http://flask-admin.readthedocs.org/en/latest/>`_.
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::
To build the docs in your local environment, from the project directory::
sudo pip install sphinx
cd flask-admin
pip install -r requirements-dev.txt
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/>`_.
And 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
------------
......@@ -69,7 +69,7 @@ To install Flask-Admin, simply::
Or alternatively, you can download the repository and install manually by doing::
git clone git@github.com:mrjoes/flask-admin.git
git clone git@github.com:flask-admin/flask-admin.git
cd flask-admin
python setup.py install
......@@ -77,22 +77,23 @@ Tests
-----
Test are run with *nose*. If you are not familiar with this package you can get some more info from `their website <http://nose.readthedocs.org/>`_.
To run the tests, simply::
To run the tests, from the project directory, simply::
pip install nose
and then::
cd flask-admin
pip install -r requirements-dev.txt
nosetests
You should see output similar to::
...
.............................................
----------------------------------------------------------------------
Ran 41 tests in 2.092s
Ran 102 tests in 13.132s
Please note that you will need to install some additional dependencies in order for all of the tests to be executed successfully.
OK
For all the tests to pass successfully, you'll need Postgres & MongoDB to be running locally. For Postgres::
CREATE DATABASE flask_admin_test;
CREATE EXTENSION postgis;
3rd Party Stuff
---------------
......@@ -100,3 +101,5 @@ Please note that you will need to install some additional dependencies in order
Flask-Admin is built with the help of `Bootstrap <http://getbootstrap.com/>`_ and `Select2 <https://github.com/ivaynberg/select2>`_.
If you want to localize your application, install the `Flask-BabelEx <https://pypi.python.org/pypi/Flask-BabelEx>`_ package.
You can help improve Flask-Admin's translations through Crowdin: https://crowdin.com/project/flask-admin
This diff is collapsed.
#!/bin/sh
# get newest translations from Crowdin
cd ../flask_admin/translations/
curl http://api.crowdin.net/api/project/flask-admin/export?key=`cat ~/.crowdin.flaskadmin.key`
wget http://api.crowdin.net/api/project/flask-admin/download/all.zip?key=`cat ~/.crowdin.flaskadmin.key` -O all.zip
# unzip and move .po files in subfolders called LC_MESSAGES
unzip -o all.zip
find . -maxdepth 2 -name "*.po" -exec bash -c 'mkdir -p $(dirname {})/LC_MESSAGES; mv {} $(dirname {})/LC_MESSAGES/admin.po' \;
rm all.zip
mv es-ES/LC_MESSAGES/* es/LC_MESSAGES/
rm -r es-ES/
mv ca/LC_MESSAGES/* ca_ES/LC_MESSAGES/
rm -r ca/
mv zh-CN/LC_MESSAGES/* zh_Hans_CN/LC_MESSAGES/
rm -r zh-CN/
mv zh-TW/LC_MESSAGES/* zh_Hant_TW/LC_MESSAGES/
rm -r zh-TW/
mv pt-PT/LC_MESSAGES/* pt/LC_MESSAGES/
rm -r pt-PT/
mv pt-BR/LC_MESSAGES/* pt_BR/LC_MESSAGES/
rm -r pt-BR/
mv sv-SE/LC_MESSAGES/* sv/LC_MESSAGES/
rm -r sv-SE/
cd ../../babel
sh babel.sh
#!/bin/sh
sh babel.sh
curl -F "files[/admin.pot]=@admin.pot" http://api.crowdin.net/api/project/flask-admin/update-file?key=`cat ~/.crowdin.flaskadmin.key`
<h3>Useful Links</h3>
<ul>
<li><a href="http://flask.pocoo.org/">The Flask Website</a></li>
<li><a href="http://github.com/mrjoes/flask-admin">Flask-Admin @ github</a></li>
<li><a href="http://github.com/flask-admin/flask-admin">Flask-Admin @ github</a></li>
</ul>
<a href="http://github.com/mrjoes/flask-admin"><img style="position: fixed; top: 0; right: 0; border: 0;"
<a href="http://github.com/flask-admin/flask-admin"><img style="position: fixed; top: 0; right: 0; border: 0;"
src="//s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
......@@ -7,4 +7,4 @@ pygments_style = flask_theme_support.FlaskyStyle
index_logo = 'flask-admin.png'
index_logo_height = 140px
touch_icon =
github_fork = 'mrjoes/flask-admin'
github_fork = 'flask-admin/flask-admin'
......@@ -7,5 +7,5 @@ pygments_style = flask_theme_support.FlaskyStyle
[options]
index_logo =
index_logo_height = 120px
github_fork = MrJoes/Flask-AdminEx
github_fork = flask-admin/flask-adminEx
``flask.ext.admin.actions``
``flask_admin.actions``
===========================
.. automodule:: flask.ext.admin.actions
.. automodule:: flask_admin.actions
.. autofunction:: action
......
``flask.ext.admin.base``
``flask_admin.base``
========================
.. automodule:: flask.ext.admin.base
.. automodule:: flask_admin.base
Base View
---------
......
``flask.ext.admin.contrib.fileadmin``
``flask_admin.contrib.fileadmin``
=====================================
.. automodule:: flask.ext.admin.contrib.fileadmin
.. automodule:: flask_admin.contrib.fileadmin
.. autoclass:: FileAdmin
:members:
......
``flask.ext.admin.contrib.mongoengine``
``flask_admin.contrib.mongoengine``
=======================================
MongoEngine model backend implementation.
.. automodule:: flask.ext.admin.contrib.mongoengine
.. automodule:: flask_admin.contrib.mongoengine
.. autoclass:: ModelView
:members:
......@@ -12,7 +12,7 @@ MongoEngine model backend implementation.
filter_converter, model_form_converter
allowed_search_types, form_subdocuments
Class inherits configuration options from :class:`~flask.ext.admin.model.BaseModelView` and they're not displayed here.
Class inherits configuration options from :class:`~flask_admin.model.BaseModelView` and they're not displayed here.
.. autoattribute:: column_filters
.. autoattribute:: column_type_formatters
......
``flask.ext.admin.contrib.mongoengine.fields``
``flask_admin.contrib.mongoengine.fields``
==============================================
.. automodule:: flask.ext.admin.contrib.mongoengine.fields
.. automodule:: flask_admin.contrib.mongoengine.fields
.. autoclass:: ModelFormField
:members:
......@@ -11,4 +11,3 @@
.. autoclass:: MongoImageField
:members:
``flask.ext.admin.contrib.peewee``
``flask_admin.contrib.peewee``
==================================
Peewee model backend implementation.
.. automodule:: flask.ext.admin.contrib.peewee
.. automodule:: flask_admin.contrib.peewee
.. autoclass:: ModelView
:members:
......@@ -11,7 +11,7 @@ Peewee model backend implementation.
:exclude-members: column_filters, filter_converter, model_form_converter,
inline_model_form_converter, fast_mass_delete, inline_models
Class inherits configuration options from :class:`~flask.ext.admin.model.BaseModelView` and they're not displayed here.
Class inherits configuration options from :class:`~flask_admin.model.BaseModelView` and they're not displayed here.
.. autoattribute:: column_filters
.. autoattribute:: filter_converter
......
``flask.ext.admin.contrib.pymongo``
``flask_admin.contrib.pymongo``
===================================
PyMongo model backend implementation.
.. automodule:: flask.ext.admin.contrib.pymongo
.. automodule:: flask_admin.contrib.pymongo
.. autoclass:: ModelView
:members:
:inherited-members:
:exclude-members: column_filters
Class inherits configuration options from :class:`~flask.ext.admin.model.BaseModelView` and they're not displayed here.
Class inherits configuration options from :class:`~flask_admin.model.BaseModelView` and they're not displayed here.
.. autoattribute:: column_filters
``flask.ext.admin.contrib.sqla``
``flask_admin.contrib.sqla``
================================
SQLAlchemy model backend implementation.
.. automodule:: flask.ext.admin.contrib.sqla
.. automodule:: flask_admin.contrib.sqla
.. autoclass:: ModelView
:members:
......@@ -15,7 +15,7 @@ SQLAlchemy model backend implementation.
inline_models, form_choices,
form_optional_types
Class inherits configuration options from :class:`~flask.ext.admin.model.BaseModelView` and they're not displayed here.
Class inherits configuration options from :class:`~flask_admin.model.BaseModelView` and they're not displayed here.
.. autoattribute:: column_auto_select_related
.. autoattribute:: column_select_related_list
......
``flask.ext.admin.form``
``flask_admin.form``
========================
.. automodule:: flask.ext.admin.form
.. automodule:: flask_admin.form
.. autoclass:: BaseForm
:members:
``flask.ext.admin.form.fields``
===============================
``flask_admin.form.fields``
===========================
.. automodule:: flask.ext.admin.form.fields
.. automodule:: flask_admin.form.fields
.. autoclass:: TimeField
:members:
......
``flask.ext.admin.form.rules``
==============================
``flask_admin.form.rules``
==========================
.. automodule:: flask.ext.admin.form.rules
.. automodule:: flask_admin.form.rules
.. autoclass:: BaseRule
:members: __init__
......@@ -35,4 +35,3 @@
.. autoclass:: FieldSet
:members: __init__
``flask.ext.admin.form.upload``
``flask_admin.form.upload``
===============================
.. automodule:: flask.ext.admin.form.upload
.. automodule:: flask_admin.form.upload
.. autoclass:: FileUploadField
:members: __init__
......
``flask.ext.admin.helpers``
``flask_admin.helpers``
===========================
.. automodule:: flask.ext.admin.helpers
.. automodule:: flask_admin.helpers
.. autofunction:: get_current_view
......@@ -17,4 +17,3 @@
.. autofunction:: resolve_ctx
.. autofunction:: get_render_ctx
``flask.ext.admin.model``
``flask_admin.model``
=========================
.. automodule:: flask.ext.admin.model
.. automodule:: flask_admin.model
.. autoclass:: BaseModelView
:members:
......
``flask.ext.admin.model.template``
``flask_admin.model.template``
==================================
.. automodule:: flask.ext.admin.model.template
.. automodule:: flask_admin.model.template
.. autofunction:: macro
``flask.ext.admin.tools``
``flask_admin.tools``
=========================
.. automodule:: flask.ext.admin.tools
.. automodule:: flask_admin.tools
.. autofunction:: import_module
.. autofunction:: import_attribute
.. autofunction:: module_not_found
.. autofunction:: rec_getattr
......@@ -28,6 +28,10 @@ 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
......@@ -42,7 +46,7 @@ changes necessary to other code. ``ModelView`` should be imported from
``geoa`` rather than the one imported from ``sqla``::
from geoalchemy2 import Geometry
from flask.ext.admin.contrib.geoa import ModelView
from flask_admin.contrib.geoa import ModelView
# .. flask initialization
db = SQLAlchemy(app)
......
......@@ -21,4 +21,4 @@ Known issues:
For more documentation, check :doc:`api/mod_contrib_mongoengine` documentation.
MongoEngine integration example is `here <https://github.com/mrjoes/flask-admin/tree/master/examples/mongoengine>`_.
MongoEngine integration example is `here <https://github.com/flask-admin/flask-admin/tree/master/examples/mongoengine>`_.
......@@ -15,4 +15,4 @@ Known issues:
For more documentation, check :doc:`api/mod_contrib_peewee` documentation.
Peewee example is `here <https://github.com/mrjoes/flask-admin/tree/master/examples/peewee>`_.
Peewee example is `here <https://github.com/flask-admin/flask-admin/tree/master/examples/peewee>`_.
......@@ -11,7 +11,7 @@ with PyMongo:
1. Provide list of columns by setting `column_list` property
2. Provide form to use by setting `form` property
3. When instantiating :class:`flask.ext.admin.contrib.pymongo.ModelView` class, you have to provide PyMongo collection object
3. When instantiating :class:`flask_admin.contrib.pymongo.ModelView` class, you have to provide PyMongo collection object
This is minimal PyMongo view::
......@@ -33,4 +33,4 @@ On top of that you can add sortable columns, filters, text search, etc.
For more documentation, check :doc:`api/mod_contrib_pymongo` documentation.
PyMongo integration example is `here <https://github.com/mrjoes/flask-admin/tree/master/examples/pymongo>`_.
PyMongo integration example is `here <https://github.com/flask-admin/flask-admin/tree/master/examples/pymongo>`_.
......@@ -22,9 +22,9 @@ If you use Flask-SQLAlchemy, this is how you initialize Flask-Admin
and get session from the `SQLAlchemy` object::
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.admin import Admin
from flask.ext.admin.contrib.sqla import ModelView
from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
app = Flask(__name__)
# .. read settings
......@@ -73,7 +73,7 @@ Customizing administrative interface
List view can be customized in different ways.
First of all, you can use various class-level properties to configure
what should be displayed and how. For example, :attr:`~flask.ext.admin.contrib.sqla.ModelView.column_list` can be used to show some of
what should be displayed and how. For example, :attr:`~flask_admin.contrib.sqla.ModelView.column_list` can be used to show some of
the column or include extra columns from related models.
For example::
......@@ -89,7 +89,7 @@ For example::
# Add filters for name and email columns
column_filters = ('name', 'email')
Alternatively, you can override some of the :class:`~flask.ext.admin.contrib.sqla.ModelView` methods and implement your custom logic.
Alternatively, you can override some of the :class:`~flask_admin.contrib.sqla.ModelView` methods and implement your custom logic.
For example, if you need to contribute additional field to the generated form,
you can do something like this::
......@@ -148,4 +148,4 @@ Example
-------
Flask-Admin comes with relatively advanced example, which you can
see `here <https://github.com/mrjoes/flask-admin/tree/master/examples/sqla>`_.
see `here <https://github.com/flask-admin/flask-admin/tree/master/examples/sqla>`_.
......@@ -43,9 +43,9 @@ Let's write a bit of code to create a simple CRUD interface for the `Post` SQLAl
Flask-SQLAlchemy extension, but you don't have to use it (you could also use the SQLAlchemy declarative extension)::
from flask import Flask
from flask.ext.admin import Admin
from flask.ext.admin.contrib.sqla import ModelView
from flask.ext.sqlalchemy import SQLAlchemy
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
......@@ -91,17 +91,17 @@ SQLAlchemy backend. You can also see which *django-admin* properties they corres
Django Flask-Admin
=========================================== ==============================================
actions :doc:`api/mod_actions`
exclude :attr:`~flask.ext.admin.model.BaseModelView.form_excluded_columns`
fields :attr:`~flask.ext.admin.model.BaseModelView.form_columns`
form :attr:`~flask.ext.admin.model.BaseModelView.form`
formfield_overrides :attr:`~flask.ext.admin.model.BaseModelView.form_args`
inlines :attr:`~flask.ext.admin.contrib.sqlalchemy.ModelView.inline_models`
list_display :attr:`~flask.ext.admin.model.BaseModelView.column_list`
list_filter :attr:`~flask.ext.admin.contrib.sqlalchemy.ModelView.column_filters`
list_per_page :attr:`~flask.ext.admin.model.BaseModelView.page_size`
search_fields :attr:`~flask.ext.admin.model.BaseModelView.column_searchable_list`
add_form_template :attr:`~flask.ext.admin.model.BaseModelView.create_template`
change_form_template :attr:`~flask.ext.admin.model.BaseModelView.change_form_template`
exclude :attr:`~flask_admin.model.BaseModelView.form_excluded_columns`
fields :attr:`~flask_admin.model.BaseModelView.form_columns`
form :attr:`~flask_admin.model.BaseModelView.form`
formfield_overrides :attr:`~flask_admin.model.BaseModelView.form_args`
inlines :attr:`~flask_admin.contrib.sqlalchemy.ModelView.inline_models`
list_display :attr:`~flask_admin.model.BaseModelView.column_list`
list_filter :attr:`~flask_admin.contrib.sqlalchemy.ModelView.column_filters`
list_per_page :attr:`~flask_admin.model.BaseModelView.page_size`
search_fields :attr:`~flask_admin.model.BaseModelView.column_searchable_list`
add_form_template :attr:`~flask_admin.model.BaseModelView.create_template`
change_form_template :attr:`~flask_admin.model.BaseModelView.change_form_template`
=========================================== ==============================================
You might want to check :doc:`api/mod_model` for basic model configuration options (reused by all model
......@@ -152,10 +152,9 @@ Tips and hints
it instead of default implementation.
3. Using Jinja2, you can easily extend the existing templates. You can even change the look and feel of the admin
interface completely, if you want to. Check `this example <https://github.com/mrjoes/flask-admin/tree/master/examples/layout>`_.
interface completely, if you want to. Check `this example <https://github.com/flask-admin/flask-admin/tree/master/examples/layout>`_.
4. You are not limited to a simple CRUD interface for every model. Want to add some kind of realtime monitoring via websockets? No problem.
5. There's a so called "index view". By default it is empty, but you can put any information you need there. It is displayed
under the *Home* menu option.
......@@ -27,12 +27,12 @@ property one of your admin views::
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.ext.admin.form.rules.Field` class instance for that field.
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.ext.admin.form.rules.Text` class::
using the :class:`flask_admin.form.rules.Text` class::
from flask.ext.admin.form import rules
from flask_admin.form import rules
class RuleView(sqla.ModelView):
form_create_rules = ('email', rules.Text('Foobar'), 'first_name', 'last_name')
......@@ -40,25 +40,25 @@ using the :class:`flask.ext.admin.form.rules.Text` class::
Built-in rules
--------------
Flask-Admin comes with few built-in rules that can be found in the :mod:`flask.ext.admin.form.rules` module:
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.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
:class:`flask.ext.admin.form.rules.Text` Simple text rendering rule
:class:`flask.ext.admin.form.rules.HTML` Same as `Text` rule, but does not escape the text
:class:`flask.ext.admin.form.rules.Macro` Calls macro from current Jinja2 context
:class:`flask.ext.admin.form.rules.Container` Wraps child rules into container rendered by macro
:class:`flask.ext.admin.form.rules.Field` Renders single form field
:class:`flask.ext.admin.form.rules.Header` Renders form header
:class:`flask.ext.admin.form.rules.FieldSet` Renders form header and child rules
: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.ext.admin.form.BaseForm` by using :attr:`flask.ext.admin.model.BaseModelView.form_base_class`.
------------------------
Adding CSRF validation will require overriding the :class:`flask_admin.form.BaseForm` by using :attr:`flask_admin.model.BaseModelView.form_base_class`.
WTForms >=2::
......@@ -66,8 +66,8 @@ WTForms >=2::
from wtforms.meta import DefaultMeta
from flask import session
from datetime import timedelta
from flask.ext.admin import form
from flask.ext.admin.contrib import sqla
from flask_admin import form
from flask_admin.contrib import sqla
class SecureForm(form.BaseForm):
class Meta(DefaultMeta):
......@@ -122,5 +122,5 @@ For WTForms 1, you can use use Flask-WTF's Form class::
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 <https://github.com/mrjoes/flask-admin/tree/master/examples/forms>`_ on GitHub.
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.
......@@ -6,7 +6,7 @@ add admin interfaces to Flask applications. It is inspired by the *django-admin*
a way that the developer has total control of the look, feel and functionality of the resulting application.
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.
`our GitHub repository <http://github.com/flask-admin/flask-admin>`_ to find out how you can contribute to the project.
.. toctree::
:maxdepth: 2
......
......@@ -2,7 +2,7 @@ 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/mrjoes/flask-babelex/>`_ package for handling translations. This package is a
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
......@@ -21,7 +21,7 @@ How to enable localization
2. Initialize Flask-BabelEx by creating instance of `Babel` class::
from flask import app
from flask.ext.babelex import Babel
from flask_babelex import Babel
app = Flask(__name__)
babel = Babel(app)
......
......@@ -14,7 +14,7 @@ and implementing the set of scaffolding methods listed below.
Extending BaseModelView
-------------------------
Start off by defining a new class, which derives from from :class:`~flask.ext.admin.model.BaseModelView`::
Start off by defining a new class, which derives from from :class:`~flask_admin.model.BaseModelView`::
class MyDbModel(BaseModelView):
pass
......@@ -24,11 +24,11 @@ Extending BaseModelView
Now, implement the following scaffolding methods for the new class:
1. :meth:`~flask.ext.admin.model.BaseModelView.get_pk_value`
1. :meth:`~flask_admin.model.BaseModelView.get_pk_value`
This method returns a primary key value from
the model instance. In the SQLAlchemy backend, it gets the primary key from the model
using :meth:`~flask.ext.admin.contrib.sqla.ModelView.scaffold_pk`, caches it
using :meth:`~flask_admin.contrib.sqla.ModelView.scaffold_pk`, caches it
and then returns the value from the model whenever requested.
For example::
......@@ -37,7 +37,7 @@ Extending BaseModelView
def get_pk_value(self, model):
return self.model.id
2. :meth:`~flask.ext.admin.model.BaseModelView.scaffold_list_columns`
2. :meth:`~flask_admin.model.BaseModelView.scaffold_list_columns`
Returns a list of columns to be displayed in a list view. For example::
......@@ -52,7 +52,7 @@ Extending BaseModelView
return columns
3. :meth:`~flask.ext.admin.model.BaseModelView.scaffold_sortable_columns`
3. :meth:`~flask_admin.model.BaseModelView.scaffold_sortable_columns`
Returns a dictionary of sortable columns. The keys in the dictionary should correspond to the model's
field names. The values should be those variables that will be used for sorting.
......@@ -64,7 +64,7 @@ Extending BaseModelView
If your backend does not support sorting, return
`None` or an empty dictionary.
4. :meth:`~flask.ext.admin.model.BaseModelView.init_search`
4. :meth:`~flask_admin.model.BaseModelView.init_search`
Initialize search functionality. If your backend supports
full-text search, do initializations and return `True`.
......@@ -76,7 +76,7 @@ Extending BaseModelView
it will add a join, etc) and caches this information for
future use.
5. :meth:`~flask.ext.admin.model.BaseModelView.scaffold_form`
5. :meth:`~flask_admin.model.BaseModelView.scaffold_form`
Generate `WTForms` form class from the model.
......@@ -90,7 +90,7 @@ Extending BaseModelView
# Do something
return MyForm
6. :meth:`~flask.ext.admin.model.BaseModelView.get_list`
6. :meth:`~flask_admin.model.BaseModelView.get_list`
This method should return list of model instances with paging,
sorting, etc applied.
......@@ -120,27 +120,27 @@ Extending BaseModelView
6. Return count, list as a tuple
7. :meth:`~flask.ext.admin.model.BaseModelView.get_one`
7. :meth:`~flask_admin.model.BaseModelView.get_one`
Return a model instance by its primary key.
8. :meth:`~flask.ext.admin.model.BaseModelView.create_model`
8. :meth:`~flask_admin.model.BaseModelView.create_model`
Create a new instance of the model from the `Form` object.
9. :meth:`~flask.ext.admin.model.BaseModelView.update_model`
9. :meth:`~flask_admin.model.BaseModelView.update_model`
Update the model instance with data from the form.
10. :meth:`~flask.ext.admin.model.BaseModelView.delete_model`
10. :meth:`~flask_admin.model.BaseModelView.delete_model`
Delete the specified model instance from the data store.
11. :meth:`~flask.ext.admin.model.BaseModelView.is_valid_filter`
11. :meth:`~flask_admin.model.BaseModelView.is_valid_filter`
Verify whether the given object is a valid filter.
12. :meth:`~flask.ext.admin.model.BaseModelView.scaffold_filters`
12. :meth:`~flask_admin.model.BaseModelView.scaffold_filters`
Return a list of filter objects for one model field.
......@@ -166,17 +166,17 @@ Implementing filters
filters from SQLAlchemy models in a non-SQLAlchemy backend.
This also means that different backends might have different set of available filters.
The filter is a class derived from :class:`~flask.ext.admin.model.filters.BaseFilter` which implements at least two methods:
The filter is a class derived from :class:`~flask_admin.model.filters.BaseFilter` which implements at least two methods:
1. :meth:`~flask.ext.admin.model.filters.BaseFilter.apply`
2. :meth:`~flask.ext.admin.model.filters.BaseFilter.operation`
1. :meth:`~flask_admin.model.filters.BaseFilter.apply`
2. :meth:`~flask_admin.model.filters.BaseFilter.operation`
`apply` method accepts two parameters: `query` object and a value from the client. Here you can add
filtering logic for the filter type.
Lets take SQLAlchemy model backend as an example:
All SQLAlchemy filters derive from :class:`~flask.ext.admin.contrib.sqla.filters.BaseSQLAFilter` class.
All SQLAlchemy filters derive from :class:`~flask_admin.contrib.sqla.filters.BaseSQLAFilter` class.
Each filter implements one simple filter SQL operation (like, not like, greater, etc) and accepts a column as
input parameter.
......
......@@ -41,12 +41,12 @@ or extend existing functionality by adding more views.
Initialization
--------------
To start using Flask-Admin, you have to create a :class:`~flask.ext.admin.base.Admin` class instance and associate it
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.ext.admin import Admin
from flask_admin import Admin
app = Flask(__name__)
......@@ -62,12 +62,12 @@ you should see an empty "Home" page with a navigation bar on top
:target: ../_images/quickstart_1.png
You can change the application name by passing a value for the *name* parameter to the
:class:`~flask.ext.admin.base.Admin` class constructor::
: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.ext.admin.base.Admin.init_app` function, after the Admin instance has been initialized::
:meth:`~flask_admin.base.Admin.init_app` function, after the Admin instance has been initialized::
admin = Admin(name='My App')
# Add views here
......@@ -77,10 +77,10 @@ Adding 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.ext.admin.base.BaseView` class::
and *Hello*. To do this, you need to derive from the :class:`~flask_admin.base.BaseView` class::
from flask import Flask
from flask.ext.admin import Admin, BaseView, expose
from flask_admin import Admin, BaseView, expose
class MyView(BaseView):
@expose('/')
......@@ -130,7 +130,7 @@ the Admin instance. The category specifies the name of the top-level menu item,
with it, will be accessible from a drop-down menu. For example::
from flask import Flask
from flask.ext.admin import Admin, BaseView, expose
from flask_admin import Admin, BaseView, expose
class MyView(BaseView):
@expose('/')
......@@ -185,7 +185,7 @@ Model views allow you to add dedicated admin pages for each of the models in you
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.ext.admin.contrib.sqla import ModelView
from flask_admin.contrib.sqla import ModelView
# Flask and Flask-SQLAlchemy initialization here
......@@ -204,7 +204,7 @@ 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.ext.admin.contrib.sqla import ModelView
from flask_admin.contrib.sqla import ModelView
# Flask and Flask-SQLAlchemy initialization here
......@@ -238,10 +238,10 @@ therefore should use a *SelectField*::
It is relatively easy to add support for different database backends (Mongo, etc) by inheriting from
:class:`~flask.ext.admin.model.BaseModelView`.
:class:`~flask_admin.model.BaseModelView`.
class and implementing database-related methods.
Please refer to :mod:`flask.ext.admin.contrib.sqla` documentation on how to customize the behavior of model-based
Please refer to :mod:`flask_admin.contrib.sqla` documentation on how to customize the behavior of model-based
administrative views.
File Admin
......@@ -252,7 +252,7 @@ Flask-Admin comes with another handy battery - file admin. It gives you the abil
Here is simple example::
from flask.ext.admin.contrib.fileadmin import FileAdmin
from flask_admin.contrib.fileadmin import FileAdmin
import os.path as op
......@@ -270,7 +270,7 @@ Sample screenshot:
:target: ../_images/quickstart_5.png
You can disable uploads, disable file or directory deletion, restrict file uploads to certain types and so on.
Check :mod:`flask.ext.admin.contrib.fileadmin` documentation on how to do it.
Check :mod:`flask_admin.contrib.fileadmin` documentation on how to do it.
Generating URLs
---------------
......@@ -323,35 +323,34 @@ 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/MrJoes/Flask-Admin/tree/master/examples/simple>`_
- `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/MrJoes/Flask-Admin/tree/master/examples/layout>`_
- `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/MrJoes/Flask-Admin/tree/master/examples/layout-bootstrap3>`_.
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/MrJoes/Flask-Admin/tree/master/examples/sqla>`_
- `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/MrJoes/Flask-Admin/tree/master/examples/forms>`_
- `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/MrJoes/Flask-Admin/tree/master/examples/auth>`_
- `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/MrJoes/Flask-Admin/tree/master/examples/peewee>`_
- `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/MrJoes/Flask-Admin/tree/master/examples/mongoengine>`_
- `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/MrJoes/Flask-Admin/tree/master/examples/babel>`_
- `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/MrJoes/Flask-Admin/tree/master/examples/rediscli>`_
- `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.
......@@ -122,7 +122,7 @@ admin_view Current administrative view
admin_base_template Base template name
_gettext Babel gettext
_ngettext Babel ngettext
h Helpers from :mod:`~flask.ext.admin.helpers` module
h Helpers from :mod:`~flask_admin.helpers` module
==================== ================================
......
......@@ -24,13 +24,13 @@ General tips
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.
(: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.ext.admin.form.upload`.
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.ext.admin.model.base.scaffold_form`. For example, if you use
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.
......@@ -51,4 +51,4 @@ MongoEngine
-----------
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`.
at :mod:`flask_admin.contrib.mongoengine.fields`.
This example shows how to integrate Flask-Login authentication with Flask-Admin using the SQLAlchemy backend.
To run this example:
1. Clone the repository::
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
virtualenv env
source env/bin/activate
3. Install requirements::
pip install -r 'examples/auth-flask-login/requirements.txt'
4. Run the application::
python examples/auth-flask-login/app.py
The first time you run this example, a sample sqlite database gets populated automatically. To suppress this behaviour,
comment the following lines in app.py:::
if not os.path.exists(database_path):
build_sample_db()
import os
from flask import Flask, url_for, redirect, render_template, request
from flask_sqlalchemy import SQLAlchemy
from wtforms import form, fields, validators
import flask_admin as admin
import flask_login as login
from flask_admin.contrib import sqla
from flask_admin import helpers, expose
from werkzeug.security import generate_password_hash, check_password_hash
# Create Flask application
app = Flask(__name__)
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['DATABASE_FILE'] = 'sample_db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
# Create user model.
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(100))
last_name = db.Column(db.String(100))
login = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120))
password = db.Column(db.String(64))
# Flask-Login integration
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return self.id
# Required for administrative interface
def __unicode__(self):
return self.username
# Define login and registration forms (for flask-login)
class LoginForm(form.Form):
login = fields.TextField(validators=[validators.required()])
password = fields.PasswordField(validators=[validators.required()])
def validate_login(self, field):
user = self.get_user()
if user is None:
raise validators.ValidationError('Invalid user')
# we're comparing the plaintext pw with the the hash from the db
if not check_password_hash(user.password, self.password.data):
# to compare plain text passwords use
# if user.password != self.password.data:
raise validators.ValidationError('Invalid password')
def get_user(self):
return db.session.query(User).filter_by(login=self.login.data).first()
class RegistrationForm(form.Form):
login = fields.TextField(validators=[validators.required()])
email = fields.TextField()
password = fields.PasswordField(validators=[validators.required()])
def validate_login(self, field):
if db.session.query(User).filter_by(login=self.login.data).count() > 0:
raise validators.ValidationError('Duplicate username')
# Initialize flask-login
def init_login():
login_manager = login.LoginManager()
login_manager.init_app(app)
# Create user loader function
@login_manager.user_loader
def load_user(user_id):
return db.session.query(User).get(user_id)
# Create customized model view class
class MyModelView(sqla.ModelView):
def is_accessible(self):
return login.current_user.is_authenticated()
# Create customized index view class that handles login & registration
class MyAdminIndexView(admin.AdminIndexView):
@expose('/')
def index(self):
if not login.current_user.is_authenticated():
return redirect(url_for('.login_view'))
return super(MyAdminIndexView, self).index()
@expose('/login/', methods=('GET', 'POST'))
def login_view(self):
# handle user login
form = LoginForm(request.form)
if helpers.validate_form_on_submit(form):
user = form.get_user()
login.login_user(user)
if login.current_user.is_authenticated():
return redirect(url_for('.index'))
link = '<p>Don\'t have an account? <a href="' + url_for('.register_view') + '">Click here to register.</a></p>'
self._template_args['form'] = form
self._template_args['link'] = link
return super(MyAdminIndexView, self).index()
@expose('/register/', methods=('GET', 'POST'))
def register_view(self):
form = RegistrationForm(request.form)
if helpers.validate_form_on_submit(form):
user = User()
form.populate_obj(user)
# we hash the users password to avoid saving it as plaintext in the db,
# remove to use plain text:
user.password = generate_password_hash(form.password.data)
db.session.add(user)
db.session.commit()
login.login_user(user)
return redirect(url_for('.index'))
link = '<p>Already have an account? <a href="' + url_for('.login_view') + '">Click here to log in.</a></p>'
self._template_args['form'] = form
self._template_args['link'] = link
return super(MyAdminIndexView, self).index()
@expose('/logout/')
def logout_view(self):
login.logout_user()
return redirect(url_for('.index'))
# Flask views
@app.route('/')
def index():
return render_template('index.html')
# Initialize flask-login
init_login()
# Create admin
admin = admin.Admin(app, 'Example: Auth', index_view=MyAdminIndexView(), base_template='my_master.html')
# Add view
admin.add_view(MyModelView(User, db.session))
def build_sample_db():
"""
Populate a small db with some example entries.
"""
import string
import random
db.drop_all()
db.create_all()
# passwords are hashed, to use plaintext passwords instead:
# test_user = User(login="test", password="test")
test_user = User(login="test", password=generate_password_hash("test"))
db.session.add(test_user)
first_names = [
'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie','Sophie', 'Mia',
'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
]
last_names = [
'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas',
'Roberts', 'Khan', 'Lewis', 'Jackson', 'Clarke', 'James', 'Phillips', 'Wilson',
'Ali', 'Mason', 'Mitchell', 'Rose', 'Davis', 'Davies', 'Rodriguez', 'Cox', 'Alexander'
]
for i in range(len(first_names)):
user = User()
user.first_name = first_names[i]
user.last_name = last_names[i]
user.login = user.first_name.lower()
user.email = user.login + "@example.com"
user.password = generate_password_hash(''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(10)))
db.session.add(user)
db.session.commit()
return
if __name__ == '__main__':
# Build a sample db on the fly, if one does not exist yet.
app_dir = os.path.realpath(os.path.dirname(__file__))
database_path = os.path.join(app_dir, app.config['DATABASE_FILE'])
if not os.path.exists(database_path):
build_sample_db()
# Start app
app.run(debug=True)
Flask
Flask-Admin
Flask-SQLAlchemy
Flask-Login
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="row-fluid">
<div>
{% if current_user.is_authenticated() %}
<h1>Flask-Admin example</h1>
<p class="lead">
Authentication
</p>
<p>
This example shows how you can use Flask-Login for authentication. It is only intended as a basic demonstration.
</p>
{% else %}
<form method="POST" action="">
{{ form.hidden_tag() if form.hidden_tag }}
{% for f in form if f.type != 'CSRFTokenField' %}
<div>
{{ f.label }}
{{ f }}
{% if f.errors %}
<ul>
{% for e in f.errors %}
<li>{{ e }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endfor %}
<button class="btn" type="submit">Submit</button>
</form>
{{ link | safe }}
{% endif %}
</div>
<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
<html>
<body>
<div>
<a href="{{ url_for('admin.index') }}">Go to admin!</a>
</div>
</body>
</html>
{% extends 'admin/base.html' %}
{% block access_control %}
{% if current_user.is_authenticated() %}
<div class="btn-group pull-right">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<i class="icon-user"></i> {{ current_user.login }} <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="{{ url_for('admin.logout_view') }}">Log out</a></li>
</ul>
</div>
{% endif %}
{% endblock %}
\ No newline at end of file
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
from flask import Flask, url_for, redirect, render_template, request
from flask.ext.mongoengine import MongoEngine
from flask_mongoengine import MongoEngine
from wtforms import form, fields, validators
from flask.ext import admin, login
from flask.ext.admin.contrib.mongoengine import ModelView
from flask.ext.admin import helpers
import flask_admin as admin
import flask_login as login
from flask_admin.contrib.mongoengine import ModelView
from flask_admin import helpers
# Create application
app = Flask(__name__)
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
import os
from flask import Flask, url_for, redirect, render_template, request
from flask.ext.sqlalchemy import SQLAlchemy
from wtforms import form, fields, validators
from flask.ext import admin, login
from flask.ext.admin.contrib import sqla
from flask.ext.admin import helpers, expose
from werkzeug.security import generate_password_hash, check_password_hash
from flask import Flask, url_for, redirect, render_template, request, abort
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, \
UserMixin, RoleMixin, login_required, current_user
from flask_security.utils import encrypt_password
import flask_admin as admin
from flask_admin.contrib import sqla
from flask_admin import helpers as admin_helpers
# Create Flask application
app = Flask(__name__)
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'
# Create in-memory database
app.config['DATABASE_FILE'] = 'sample_db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
app.config.from_pyfile('config.py')
db = SQLAlchemy(app)
# Create user model.
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(100))
last_name = db.Column(db.String(100))
login = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120))
password = db.Column(db.String(64))
# Flask-Login integration
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return self.id
# Required for administrative interface
def __unicode__(self):
return self.username
# Define login and registration forms (for flask-login)
class LoginForm(form.Form):
login = fields.TextField(validators=[validators.required()])
password = fields.PasswordField(validators=[validators.required()])
def validate_login(self, field):
user = self.get_user()
if user is None:
raise validators.ValidationError('Invalid user')
# we're comparing the plaintext pw with the the hash from the db
if not check_password_hash(user.password, self.password.data):
# to compare plain text passwords use
# if user.password != self.password.data:
raise validators.ValidationError('Invalid password')
# Define models
roles_users = db.Table(
'roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))
)
def get_user(self):
return db.session.query(User).filter_by(login=self.login.data).first()
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
class RegistrationForm(form.Form):
login = fields.TextField(validators=[validators.required()])
email = fields.TextField()
password = fields.PasswordField(validators=[validators.required()])
def validate_login(self, field):
if db.session.query(User).filter_by(login=self.login.data).count() > 0:
raise validators.ValidationError('Duplicate username')
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(255))
last_name = db.Column(db.String(255))
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
# Initialize flask-login
def init_login():
login_manager = login.LoginManager()
login_manager.init_app(app)
# Create user loader function
@login_manager.user_loader
def load_user(user_id):
return db.session.query(User).get(user_id)
# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
# Create customized model view class
class MyModelView(sqla.ModelView):
def is_accessible(self):
return login.current_user.is_authenticated()
# Create customized index view class that handles login & registration
class MyAdminIndexView(admin.AdminIndexView):
@expose('/')
def index(self):
if not login.current_user.is_authenticated():
return redirect(url_for('.login_view'))
return super(MyAdminIndexView, self).index()
@expose('/login/', methods=('GET', 'POST'))
def login_view(self):
# handle user login
form = LoginForm(request.form)
if helpers.validate_form_on_submit(form):
user = form.get_user()
login.login_user(user)
if login.current_user.is_authenticated():
return redirect(url_for('.index'))
link = '<p>Don\'t have an account? <a href="' + url_for('.register_view') + '">Click here to register.</a></p>'
self._template_args['form'] = form
self._template_args['link'] = link
return super(MyAdminIndexView, self).index()
@expose('/register/', methods=('GET', 'POST'))
def register_view(self):
form = RegistrationForm(request.form)
if helpers.validate_form_on_submit(form):
user = User()
form.populate_obj(user)
# we hash the users password to avoid saving it as plaintext in the db,
# remove to use plain text:
user.password = generate_password_hash(form.password.data)
db.session.add(user)
db.session.commit()
if not current_user.is_active() or not current_user.is_authenticated():
return False
login.login_user(user)
return redirect(url_for('.index'))
link = '<p>Already have an account? <a href="' + url_for('.login_view') + '">Click here to log in.</a></p>'
self._template_args['form'] = form
self._template_args['link'] = link
return super(MyAdminIndexView, self).index()
if current_user.has_role('superuser'):
return True
@expose('/logout/')
def logout_view(self):
login.logout_user()
return redirect(url_for('.index'))
return False
def _handle_view(self, name, **kwargs):
"""
Override builtin _handle_view in order to redirect users when a view is not accessible.
"""
if not self.is_accessible():
if current_user.is_authenticated():
# permission denied
abort(403)
else:
# login
return redirect(url_for('security.login', next=request.url))
# Flask views
@app.route('/')
def index():
return render_template('index.html')
# Initialize flask-login
init_login()
# Create admin
admin = admin.Admin(app, 'Example: Auth', index_view=MyAdminIndexView(), base_template='my_master.html')
admin = admin.Admin(app, 'Example: Auth', base_template='my_master.html')
# Add view
# Add model views
admin.add_view(MyModelView(Role, db.session))
admin.add_view(MyModelView(User, db.session))
# define a context processor for merging flask-admin's template context into the
# flask-security views.
@security.context_processor
def security_context_processor():
return dict(
admin_base_template=admin.base_template,
admin_view=admin.index_view,
h=admin_helpers,
)
def build_sample_db():
"""
......@@ -174,13 +103,23 @@ def build_sample_db():
db.drop_all()
db.create_all()
# passwords are hashed, to use plaintext passwords instead:
# test_user = User(login="test", password="test")
test_user = User(login="test", password=generate_password_hash("test"))
db.session.add(test_user)
with app.app_context():
user_role = Role(name='user')
super_user_role = Role(name='superuser')
db.session.add(user_role)
db.session.add(super_user_role)
db.session.commit()
test_user = user_datastore.create_user(
first_name='Admin',
email='admin',
password=encrypt_password('admin'),
roles=[user_role, super_user_role]
)
first_names = [
'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie','Sophie', 'Mia',
'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie', 'Sophie', 'Mia',
'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
]
......@@ -191,14 +130,15 @@ def build_sample_db():
]
for i in range(len(first_names)):
user = User()
user.first_name = first_names[i]
user.last_name = last_names[i]
user.login = user.first_name.lower()
user.email = user.login + "@example.com"
user.password = generate_password_hash(''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(10)))
db.session.add(user)
tmp_email = first_names[i].lower() + "." + last_names[i].lower() + "@example.com"
tmp_pass = ''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(10))
user_datastore.create_user(
first_name=first_names[i],
last_name=last_names[i],
email=tmp_email,
password=encrypt_password(tmp_pass),
roles=[user_role, ]
)
db.session.commit()
return
......
# Create dummy secrey key so we can use sessions
SECRET_KEY = '123456790'
# Create in-memory database
DATABASE_FILE = 'sample_db.sqlite'
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + DATABASE_FILE
SQLALCHEMY_ECHO = True
# Flask-Security config
SECURITY_URL_PREFIX = "/admin"
SECURITY_PASSWORD_HASH = "pbkdf2_sha512"
SECURITY_PASSWORD_SALT = "ATGUOHAELKiubahiughaerGOJAEGj"
# Flask-Security URLs, overridden because they don't put a / at the end
SECURITY_LOGIN_URL = "/login/"
SECURITY_LOGOUT_URL = "/logout/"
SECURITY_REGISTER_URL = "/register/"
SECURITY_POST_LOGIN_VIEW = "/admin/"
SECURITY_POST_LOGOUT_VIEW = "/admin/"
SECURITY_POST_REGISTER_VIEW = "/admin/"
# Flask-Security features
SECURITY_REGISTERABLE = True
SECURITY_SEND_REGISTER_EMAIL = False
\ No newline at end of file
Flask
Flask-Admin
Flask-SQLAlchemy
Flask-Login
Flask-Security==1.7.4
\ No newline at end of file
......@@ -4,33 +4,23 @@
<div class="row-fluid">
<div>
{% if current_user.is_authenticated() %}
<h1>Flask-Admin example</h1>
<p class="lead">
Authentication
</p>
<p>
This example shows how you can use Flask-Login for authentication. It is only intended as a basic demonstration.
This example shows how you can use Flask-Security for authentication.
</p>
{% else %}
<form method="POST" action="">
{{ form.hidden_tag() if form.hidden_tag }}
{% for f in form if f.type != 'CSRFTokenField' %}
<div>
{{ f.label }}
{{ f }}
{% if f.errors %}
{% if not current_user.is_authenticated() %}
<p>You can register as a regular user, or log in as a superuser with the following credentials:
<ul>
{% for e in f.errors %}
<li>{{ e }}</li>
{% endfor %}
<li>email: <b>admin</b></li>
<li>password: <b>admin</b></li>
</ul>
{% endif %}
</div>
{% endfor %}
<button class="btn" type="submit">Submit</button>
</form>
{{ link | safe }}
</p>
<p>
<a class="btn btn-default" href="{{ url_for('security.login') }}">login</a> <a class="btn btn-default" href="{{ url_for('security.register') }}">register</a>
</p>
{% endif %}
</div>
......
......@@ -4,10 +4,15 @@
{% if current_user.is_authenticated() %}
<div class="btn-group pull-right">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<i class="icon-user"></i> {{ current_user.login }} <span class="caret"></span>
<i class="icon-user"></i>
{% if current_user.first_name -%}
{{ current_user.first_name }}
{% else -%}
{{ current_user.email }}
{%- endif %} <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="{{ url_for('admin.logout_view') }}">Log out</a></li>
<li><a href="{{ url_for('security.logout') }}">Log out</a></li>
</ul>
</div>
{% endif %}
......
{% macro render_field_with_errors(field) %}
<p>
{{ field.label }} {{ field(**kwargs)|safe }}
{% if field.errors %}
<ul>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</p>
{% endmacro %}
{% macro render_field(field) %}
<p>{{ field(**kwargs)|safe }}</p>
{% endmacro %}
\ No newline at end of file
{% if security.registerable or security.recoverable or security.confirmable %}
<h2>Menu</h2>
<ul>
<li><a href="{{ url_for_security('login') }}{% if 'next' in request.args %}?next={{ request.args.next|urlencode }}{% endif %}">Login</a></li>
{% if security.registerable %}
<li><a href="{{ url_for_security('register') }}{% if 'next' in request.args %}?next={{ request.args.next|urlencode }}{% endif %}">Register</a><br/></li>
{% endif %}
{% if security.recoverable %}
<li><a href="{{ url_for_security('forgot_password') }}">Forgot password</a><br/></li>
{% endif %}
{% if security.confirmable %}
<li><a href="{{ url_for_security('send_confirmation') }}">Confirm account</a></li>
{% endif %}
</ul>
{% endif %}
{%- with messages = get_flashed_messages(with_categories=true) -%}
{% if messages %}
<ul class="flashes">
{% for category, message in messages %}
<li class="{{ category }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{%- endwith %}
\ No newline at end of file
{% extends 'admin/master.html' %}
{% from "security/_macros.html" import render_field_with_errors, render_field %}
{% include "security/_messages.html" %}
{% block body %}
{{ super() }}
<div class="row-fluid">
<h1>Login</h1>
<form action="{{ url_for_security('login') }}" method="POST" name="login_user_form">
{{ login_user_form.hidden_tag() }}
{{ render_field_with_errors(login_user_form.email) }}
{{ render_field_with_errors(login_user_form.password) }}
{{ render_field_with_errors(login_user_form.remember) }}
{{ render_field(login_user_form.next) }}
{{ render_field(login_user_form.submit, class="btn btn-primary") }}
</form>
{% include "security/_menu.html" %}
</div>
{% endblock body %}
\ No newline at end of file
{% extends 'admin/master.html' %}
{% from "security/_macros.html" import render_field_with_errors, render_field %}
{% include "security/_messages.html" %}
{% block body %}
{{ super() }}
<div class="row-fluid">
<h1>Register</h1>
<form action="{{ url_for_security('register') }}" method="POST" name="register_user_form">
{{ register_user_form.hidden_tag() }}
{{ render_field_with_errors(register_user_form.email) }}
{{ render_field_with_errors(register_user_form.password) }}
{% if register_user_form.password_confirm %}
{{ render_field_with_errors(register_user_form.password_confirm) }}
{% endif %}
{{ render_field(register_user_form.submit, class="btn btn-primary") }}
</form>
{% include "security/_menu.html" %}
</div>
{% endblock body %}
\ No newline at end of file
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
from flask import Flask, request, session
from flask.ext.sqlalchemy import SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
from flask.ext import admin
from flask.ext.babelex import Babel
import flask_admin as admin
from flask_babelex import Babel
from flask.ext.admin.contrib import sqla
from flask_admin.contrib import sqla
# Create application
app = Flask(__name__)
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
......@@ -3,8 +3,8 @@ import os.path as op
from flask import Flask
from flask.ext import admin
from flask.ext.admin.contrib import fileadmin
import flask_admin as admin
from flask_admin.contrib import fileadmin
# Create flask app
......
......@@ -5,7 +5,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
......@@ -2,14 +2,14 @@ import os
import os.path as op
from flask import Flask, url_for
from flask.ext.sqlalchemy import SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.event import listens_for
from jinja2 import Markup
from flask.ext.admin import Admin, form
from flask.ext.admin.form import rules
from flask.ext.admin.contrib import sqla
from flask_admin import Admin, form
from flask_admin.form import rules
from flask_admin.contrib import sqla
# Create application
......
SQLAlchemy model backend integration examples.
To run this example:
1. Clone the repository::
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
virtualenv env
source env/bin/activate
3. Install requirements::
pip install -r 'examples/geo-alchemy/requirements.txt'
4. Setup the database::
psql postgres
CREATE DATABASE flask_admin_geo;
CREATE ROLE flask_admin_geo LOGIN PASSWORD 'flask_admin_geo';
GRANT ALL PRIVILEGES ON DATABASE flask_admin_geo TO flask_admin_geo;
\q
psql flask_admin_geo
CREATE EXTENSION postgis;
\q
5. Run the application::
python examples/sqla/app.py
6. You will notice that the maps are not rendered. To see them, you will have
to register for a free account at `Mapbox <https://www.mapbox.com/>`_ and set
the *MAPBOX_MAP_ID* and *MAPBOX_ACCESS_TOKEN* config variables accordingly.
\ No newline at end of file
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import flask_admin as admin
from geoalchemy2.types import Geometry
from flask_admin.contrib.geoa import ModelView
# Create application
app = Flask(__name__)
# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://flask_admin_geo:flask_admin_geo@localhost/flask_admin_geo'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
app.config['MAPBOX_MAP_ID'] = '...'
app.config['MAPBOX_ACCESS_TOKEN'] = '...'
class Point(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
point = db.Column(Geometry("POINT"))
class MultiPoint(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
point = db.Column(Geometry("MULTIPOINT"))
class Polygon(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
point = db.Column(Geometry("POLYGON"))
class MultiPolygon(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
point = db.Column(Geometry("MULTIPOLYGON"))
class LineString(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
point = db.Column(Geometry("LINESTRING"))
class MultiLineString(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
point = db.Column(Geometry("MULTILINESTRING"))
# Flask views
@app.route('/')
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
# Create admin
admin = admin.Admin(app, name='Example: GeoAlchemy')
# Add views
admin.add_view(ModelView(Point, db.session, category='Points'))
admin.add_view(ModelView(MultiPoint, db.session, category='Points'))
admin.add_view(ModelView(Polygon, db.session, category='Polygons'))
admin.add_view(ModelView(MultiPolygon, db.session, category='Polygons'))
admin.add_view(ModelView(LineString, db.session, category='Lines'))
admin.add_view(ModelView(MultiLineString, db.session, category='Lines'))
if __name__ == '__main__':
db.create_all()
# Start app
app.run(debug=True)
Flask
Flask-Admin
Flask-SQLAlchemy
shapely
geoalchemy2
psycopg2
\ No newline at end of file
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
<div class="row">
<div class="span10 offset1">
<h1>Flask-Admin example</h1>
<p class="lead">
GeoAlchemy model view.
</p>
<p>
This example shows how to manage spatial information in a GIS database.
</p>
<a class="btn btn-primary" href="/"><i class="icon-arrow-left icon-white"></i> Back</a>
</div>
</div>
{% endblock body %}
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
import os
import os.path as op
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
from flask.ext import admin
from flask.ext.admin.contrib.sqla import ModelView
import flask_admin as admin
from flask_admin.contrib.sqla import ModelView
# Create application
......
......@@ -21,6 +21,9 @@
<h2 id="brand">{{ admin_view.name|capitalize }}</h2>
{% endblock %}
{{ layout.messages() }}
{% set render_ctx = h.resolve_ctx() %}
{% block body %}{% endblock %}
</div>
</div>
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
import os
import os.path as op
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
from flask.ext import admin
from flask.ext.admin.contrib.sqla import ModelView
import flask_admin as admin
from flask_admin.contrib.sqla import ModelView
# Create application
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
from flask import Flask, redirect, url_for
from flask.ext import login
from flask.ext.login import current_user, UserMixin
from flask.ext.admin.base import MenuLink, Admin, BaseView, expose
from flask_login import current_user, UserMixin
from flask_admin.base import MenuLink, Admin, BaseView, expose
# Create fake user class for authentication
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
from flask import Flask, redirect, request
from flask.ext import admin
import flask_admin as admin
from flask.views import MethodView
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
......@@ -2,10 +2,10 @@ import datetime
from flask import Flask
from flask.ext import admin
from flask.ext.mongoengine import MongoEngine
from flask.ext.admin.form import rules
from flask.ext.admin.contrib.mongoengine import ModelView
import flask_admin as admin
from flask_mongoengine import MongoEngine
from flask_admin.form import rules
from flask_admin.contrib.mongoengine import ModelView
# Create application
app = Flask(__name__)
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
from flask import Flask
from flask.ext import admin
import flask_admin as admin
# Views
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
......@@ -2,8 +2,8 @@ from flask import Flask
import peewee
from flask.ext import admin
from flask.ext.admin.contrib.peewee import ModelView
import flask_admin as admin
from flask_admin.contrib.peewee import ModelView
app = Flask(__name__)
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
......@@ -2,13 +2,13 @@ import pymongo
from bson.objectid import ObjectId
from flask import Flask
from flask.ext import admin
import flask_admin as admin
from wtforms import form, fields
from flask.ext.admin.form import Select2Widget
from flask.ext.admin.contrib.pymongo import ModelView, filters
from flask.ext.admin.model.fields import InlineFormField, InlineFieldList
from flask_admin.form import Select2Widget
from flask_admin.contrib.pymongo import ModelView, filters
from flask_admin.model.fields import InlineFormField, InlineFieldList
# Create application
app = Flask(__name__)
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
from flask import Flask
from flask.ext.admin import Admin
from flask_admin import Admin
app = Flask(__name__)
......
from flask import Flask
from flask.ext.admin import Admin, BaseView, expose
from flask_admin import Admin, BaseView, expose
class MyView(BaseView):
......
from flask import Flask
from flask.ext.admin import Admin, BaseView, expose
from flask_admin import Admin, BaseView, expose
class MyView(BaseView):
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
......@@ -2,8 +2,8 @@ from flask import Flask
from redis import Redis
from flask.ext import admin
from flask.ext.admin.contrib import rediscli
import flask_admin as admin
from flask_admin.contrib import rediscli
# Create flask app
app = Flask(__name__)
......
......@@ -5,7 +5,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
from flask import Flask
from flask.ext import admin
import flask_admin as admin
# Create custom admin view
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
from flask.ext.admin.contrib import sqla
from flask.ext.admin import expose, Admin
from flask_admin.contrib import sqla
from flask_admin import expose, Admin
# required for creating custom filters
from flask.ext.admin.contrib.sqla.filters import BaseSQLAFilter, FilterEqual
from flask_admin.contrib.sqla.filters import BaseSQLAFilter, FilterEqual
# Create application
app = Flask(__name__)
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
......@@ -5,16 +5,16 @@ from werkzeug import secure_filename
from sqlalchemy import event
from flask import Flask, request, render_template
from flask.ext.sqlalchemy import SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
from wtforms import fields
from flask.ext import admin
from flask.ext.admin.form import RenderTemplateWidget
from flask.ext.admin.model.form import InlineFormAdmin
from flask.ext.admin.contrib.sqla import ModelView
from flask.ext.admin.contrib.sqla.form import InlineModelConverter
from flask.ext.admin.contrib.sqla.fields import InlineModelFormList
import flask_admin as admin
from flask_admin.form import RenderTemplateWidget
from flask_admin.model.form import InlineFormAdmin
from flask_admin.contrib.sqla import ModelView
from flask_admin.contrib.sqla.form import InlineModelConverter
from flask_admin.contrib.sqla.fields import InlineModelFormList
# Create application
app = Flask(__name__)
......@@ -62,10 +62,13 @@ class CustomInlineFieldListWidget(RenderTemplateWidget):
super(CustomInlineFieldListWidget, self).__init__('field_list.html')
# This InlineModelFormList will use our custom widget
# This InlineModelFormList will use our custom widget and hide row controls
class CustomInlineModelFormList(InlineModelFormList):
widget = CustomInlineFieldListWidget()
def display_row_controls(self, field):
return False
# Create custom InlineModelConverter and tell it to use our InlineModelFormList
class CustomInlineModelConverter(InlineModelConverter):
......
......@@ -4,7 +4,7 @@ To run this example:
1. Clone the repository::
git clone https://github.com/mrjoes/flask-admin.git
git clone https://github.com/flask-admin/flask-admin.git
cd flask-admin
2. Create and activate a virtual environment::
......
import os
import os.path as op
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
from wtforms import validators
from flask.ext import admin
from flask.ext.admin.contrib import sqla
from flask.ext.admin.contrib.sqla import filters
import flask_admin as admin
from flask_admin.contrib import sqla
from flask_admin.contrib.sqla import filters
# Create application
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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