Forked from Forever-Young/gist:70479b8bdc8a96f6bf4851b41ff65c3e
Created
March 28, 2017 21:35
-
-
Save gordol/fd5adb8a9876cf1643848bc448622186 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