Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save gordol/fd5adb8a9876cf1643848bc448622186 to your computer and use it in GitHub Desktop.
Save gordol/fd5adb8a9876cf1643848bc448622186 to your computer and use it in GitHub Desktop.
Cascading fields example
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