Created
February 25, 2017 21:45
-
-
Save Forever-Young/70479b8bdc8a96f6bf4851b41ff65c3e to your computer and use it in GitHub Desktop.
Cascading fields example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ModelView | |
--------- | |
# field1 (->Model1), field2 (->Model2) filtered by field1 values | |
column_filter_by = ('field2') | |
form_widget_args = { | |
'field2': { | |
'data-filter-by': 'field1', | |
} | |
} | |
form_ajax_refs = { | |
'field2': FilteredAjaxModelLoader( | |
'field2', db.session, models.Model2, | |
fields=('name',), | |
page_size=10, | |
placeholder='Choose', | |
filter_by=(models.Model1, 'field1'), | |
), | |
} | |
@expose('/ajax/lookup/') | |
def ajax_lookup(self): | |
name = request.args.get('name') | |
query = request.args.get('query') | |
offset = request.args.get('offset', type=int) | |
limit = request.args.get('limit', 10, type=int) | |
# --- | |
filter_by = request.args.get('filter_by') | |
# --- | |
loader = self._form_ajax_refs.get(name) | |
if not loader: | |
abort(404) | |
# --- | |
# for specific fields pass 'filter_by' parameter to add additional filter | |
if name in self.column_filter_by: | |
data = [loader.format(m) for m in loader.get_list(query, offset, limit, filter_by)] | |
else: | |
# --- | |
data = [loader.format(m) for m in loader.get_list(query, offset, limit)] | |
return Response(json.dumps(data), mimetype='application/json') | |
class FilteredAjaxModelLoader(QueryAjaxModelLoader): | |
def get_list(self, term, offset=0, limit=DEFAULT_PAGE_SIZE, filter_by=None): | |
query = self.session.query(self.model) | |
# --- | |
filter_by_options = self.options.get('filter_by') | |
if filter_by_options and filter_by: | |
filter_by = self.session.query(filter_by_options[0]).filter_by( | |
id=filter_by).first() | |
if filter_by: | |
query = query.filter(getattr(self.model, filter_by_options[1])==filter_by) | |
# --- | |
filters = (field.ilike(u'%%%s%%' % term) for field in self._cached_fields) | |
query = query.filter(or_(*filters)) | |
if self.order_by: | |
query = query.order_by(self.order_by) | |
return query.offset(offset).limit(limit).all() | |
templates/admin/lib.html | |
------------------------ | |
<script src="{{ static('js/admin/form_custom.js') }}"></script> | |
# instead of form.js | |
form_custom.js | |
-------------- | |
function processAjaxWidget($el, name) { | |
var multiple = $el.attr('data-multiple') == '1'; | |
// --- | |
var filter_by = $el.attr('data-filter-by'); | |
// --- | |
var opts = { | |
width: 'resolve', | |
minimumInputLength: 1, | |
placeholder: 'data-placeholder', | |
ajax: { | |
url: $el.attr('data-url'), | |
data: function(term, page) { | |
// --- | |
var result = { | |
query: term, | |
offset: (page - 1) * 10, | |
limit: 10 | |
}; | |
if (filter_by) { | |
result['filter_by'] = $('#' + filter_by).val(); | |
} | |
return result; | |
// --- | |
}, | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment