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

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

parents 574f7c82 87bd923e
...@@ -2,7 +2,7 @@ from flask import Flask ...@@ -2,7 +2,7 @@ from flask import Flask
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from flask_admin.contrib import sqla from flask_admin.contrib import sqla
from flask_admin import expose, Admin from flask_admin import Admin
# required for creating custom filters # required for creating custom filters
from flask_admin.contrib.sqla.filters import BaseSQLAFilter, FilterEqual from flask_admin.contrib.sqla.filters import BaseSQLAFilter, FilterEqual
...@@ -19,6 +19,13 @@ app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE ...@@ -19,6 +19,13 @@ app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE
app.config['SQLALCHEMY_ECHO'] = True app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app) db = SQLAlchemy(app)
# Flask views
@app.route('/')
def index():
return '<a href="/admin/">Click me to get to Admin!</a>'
# Create model # Create model
class User(db.Model): class User(db.Model):
def __init__(self, first_name, last_name, username, email): def __init__(self, first_name, last_name, username, email):
...@@ -33,13 +40,14 @@ class User(db.Model): ...@@ -33,13 +40,14 @@ class User(db.Model):
username = db.Column(db.String(80), unique=True) username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True) email = db.Column(db.String(120), unique=True)
# Required for administrative interface. For python 3 please use __str__ instead. # Required for admin interface. For python 3 please use __str__ instead.
def __unicode__(self): def __unicode__(self):
return self.username return self.username
# Create custom filter class # Create custom filter class
class FilterLastNameBrown(BaseSQLAFilter): class FilterLastNameBrown(BaseSQLAFilter):
def apply(self, query, value): def apply(self, query, value, alias=None):
if value == '1': if value == '1':
return query.filter(self.column == "Brown") return query.filter(self.column == "Brown")
else: else:
...@@ -48,18 +56,23 @@ class FilterLastNameBrown(BaseSQLAFilter): ...@@ -48,18 +56,23 @@ class FilterLastNameBrown(BaseSQLAFilter):
def operation(self): def operation(self):
return 'is Brown' return 'is Brown'
# Add custom filter and standard FilterEqual to ModelView # Add custom filter and standard FilterEqual to ModelView
class UserAdmin(sqla.ModelView): class UserAdmin(sqla.ModelView):
# each filter in the list is a filter operation (equals, not equals, etc) # each filter in the list is a filter operation (equals, not equals, etc)
# filters with the same name will appear as operations under the same filter # filters with the same name will appear as operations under the same filter
column_filters = [ column_filters = [
FilterEqual(User.last_name, 'Last Name'), FilterEqual(User.last_name, 'Last Name'),
FilterLastNameBrown(User.last_name, 'Last Name', options=(('1', 'Yes'),('0', 'No'))) FilterLastNameBrown(
User.last_name, 'Last Name', options=(('1', 'Yes'), ('0', 'No'))
)
] ]
admin = Admin(app, template_mode="bootstrap3") admin = Admin(app, template_mode="bootstrap3")
admin.add_view(UserAdmin(User, db.session)) admin.add_view(UserAdmin(User, db.session))
def build_sample_db(): def build_sample_db():
db.drop_all() db.drop_all()
db.create_all() db.create_all()
...@@ -70,6 +83,7 @@ def build_sample_db(): ...@@ -70,6 +83,7 @@ def build_sample_db():
db.session.add_all([user_obj1, user_obj2, user_obj3]) db.session.add_all([user_obj1, user_obj2, user_obj3])
db.session.commit() db.session.commit()
if __name__ == '__main__': if __name__ == '__main__':
build_sample_db() build_sample_db()
app.run(port=5000) app.run(port=5000, debug=True)
...@@ -3,6 +3,7 @@ from flask import request, redirect ...@@ -3,6 +3,7 @@ from flask import request, redirect
from flask_admin import tools from flask_admin import tools
from flask_admin._compat import text_type from flask_admin._compat import text_type
from flask_admin.helpers import get_redirect_target
def action(name, text, confirmation=None): def action(name, text, confirmation=None):
...@@ -100,7 +101,8 @@ class ActionsMixin(object): ...@@ -100,7 +101,8 @@ class ActionsMixin(object):
:param return_view: :param return_view:
Name of the view to return to after the request. Name of the view to return to after the request.
If not provided, will return user to the index view. If not provided, will return user to the return url in the form
or the list view.
""" """
action = request.form.get('action') action = request.form.get('action')
ids = request.form.getlist('rowid') ids = request.form.getlist('rowid')
...@@ -113,9 +115,9 @@ class ActionsMixin(object): ...@@ -113,9 +115,9 @@ class ActionsMixin(object):
if response is not None: if response is not None:
return response return response
if not return_view: if return_view:
url = self.get_url('.' + self._default_view)
else:
url = self.get_url('.' + return_view) url = self.get_url('.' + return_view)
else:
url = get_redirect_target() or self.get_url('.index_view')
return redirect(url) return redirect(url)
...@@ -2,7 +2,7 @@ from flask import json ...@@ -2,7 +2,7 @@ from flask import json
from jinja2 import escape from jinja2 import escape
from wtforms.widgets import HTMLString, html_params from wtforms.widgets import HTMLString, html_params
from flask_admin._compat import as_unicode from flask_admin._compat import as_unicode, text_type
from flask_admin.babel import gettext from flask_admin.babel import gettext
from flask_admin.helpers import get_url from flask_admin.helpers import get_url
from flask_admin.form import RenderTemplateWidget from flask_admin.form import RenderTemplateWidget
...@@ -113,7 +113,14 @@ class XEditableWidget(object): ...@@ -113,7 +113,14 @@ class XEditableWidget(object):
kwargs['data-role'] = 'x-editable-boolean' kwargs['data-role'] = 'x-editable-boolean'
elif subfield.type == 'Select2Field': elif subfield.type == 'Select2Field':
kwargs['data-type'] = 'select' kwargs['data-type'] = 'select'
kwargs['data-source'] = dict(subfield.choices) choices = [{'value': x, 'text': y} for x, y in subfield.choices]
# prepend a blank field to choices if allow_blank = True
if getattr(subfield, 'allow_blank', False):
choices.insert(0, {'value': '__None', 'text': ''})
# json.dumps fixes issue with unicode strings not loading correctly
kwargs['data-source'] = json.dumps(choices)
elif subfield.type == 'DateField': elif subfield.type == 'DateField':
kwargs['data-type'] = 'combodate' kwargs['data-type'] = 'combodate'
kwargs['data-format'] = 'YYYY-MM-DD' kwargs['data-format'] = 'YYYY-MM-DD'
...@@ -135,20 +142,22 @@ class XEditableWidget(object): ...@@ -135,20 +142,22 @@ class XEditableWidget(object):
kwargs['data-type'] = 'number' kwargs['data-type'] = 'number'
kwargs['data-step'] = 'any' kwargs['data-step'] = 'any'
elif subfield.type in ['QuerySelectField', 'ModelSelectField']: elif subfield.type in ['QuerySelectField', 'ModelSelectField']:
# QuerySelectField and ModelSelectField are for relations
kwargs['data-type'] = 'select' kwargs['data-type'] = 'select'
choices = {} choices = []
for choice in subfield: for choice in subfield:
try: try:
choices[str(choice._value())] = str(choice.label.text) choices.append({'value': text_type(choice._value()),
'text': text_type(choice.label.text)})
except TypeError: except TypeError:
choices[str(choice._value())] = "" # unable to display text value
kwargs['data-source'] = choices choices.append({'value': text_type(choice._value()),
'text': ''})
# blank field is already included if allow_blank
kwargs['data-source'] = json.dumps(choices)
else: else:
raise Exception('Unsupported field type: %s' % (type(subfield),)) raise Exception('Unsupported field type: %s' % (type(subfield),))
# for Select2, QuerySelectField, and ModelSelectField
if getattr(subfield, 'allow_blank', False):
kwargs['data-source']['__None'] = ""
return kwargs return kwargs
...@@ -141,7 +141,7 @@ var AdminFilters = function(element, filtersElement, filterGroups, activeFilters ...@@ -141,7 +141,7 @@ var AdminFilters = function(element, filtersElement, filterGroups, activeFilters
var filter = subfilters[filterSelection]; var filter = subfilters[filterSelection];
var $inputContainer = $('<td/>').appendTo($el); var $inputContainer = $('<td/>').appendTo($el);
var $newFilterField = createFilterInput($inputContainer, filterValue, filter); var $newFilterField = createFilterInput($inputContainer, filterValue, filter).focus();
var $styledFilterField = styleFilterInput(filter, $newFilterField); var $styledFilterField = styleFilterInput(filter, $newFilterField);
return $styledFilterField; return $styledFilterField;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
{% if csrf_token %} {% if csrf_token %}
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
{% endif %} {% endif %}
<input type="hidden" name="url" value="{{ return_url }}">
<input type="hidden" id="action" name="action" /> <input type="hidden" id="action" name="action" />
</form> </form>
{% endif %} {% endif %}
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
</li> </li>
{%- endif -%} {%- endif -%}
<li class="active"> <li class="active">
<a href="javascript:void(0)">{{ _gettext('View Record') }}</a> <a href="javascript:void(0)">{{ _gettext('Details') }}</a>
</li> </li>
</ul> </ul>
{% endblock %} {% endblock %}
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
{% if csrf_token %} {% if csrf_token %}
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
{% endif %} {% endif %}
<input type="hidden" name="url" value="{{ return_url }}">
<input type="hidden" id="action" name="action" /> <input type="hidden" id="action" name="action" />
</form> </form>
{% endif %} {% endif %}
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
</li> </li>
{%- endif -%} {%- endif -%}
<li class="active"> <li class="active">
<a href="javascript:void(0)">{{ _gettext('View Record') }}</a> <a href="javascript:void(0)">{{ _gettext('Details') }}</a>
</li> </li>
</ul> </ul>
{% endblock %} {% endblock %}
......
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