Commit 55de42a7 authored by Serge S. Koval's avatar Serge S. Koval

New ajax refs configuration format for mongoengine/peewee backends

parent ce5b36ef
......@@ -5,17 +5,38 @@ from flask.ext.admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE
class QueryAjaxModelLoader(AjaxModelLoader):
def __init__(self, name, model, fields):
def __init__(self, name, model, **options):
"""
Constructor.
:param fields:
Fields to run query against
"""
super(QueryAjaxModelLoader, self).__init__(name)
super(QueryAjaxModelLoader, self).__init__(name, options)
self.model = model
self.fields = fields
self.fields = options.get('fields')
self._cached_fields = self._process_fields()
if not self.fields:
raise ValueError('AJAX loading requires `fields` to be specified for %s.%s' % (model, self.name))
def _process_fields(self):
remote_fields = []
for field in self.fields:
if isinstance(field, string_types):
attr = getattr(self.model, field, None)
if not attr:
raise ValueError('%s.%s does not exist.' % (self.model, field))
remote_fields.append(attr)
else:
remote_fields.append(field)
return remote_fields
def format(self, model):
if not model:
......@@ -31,7 +52,7 @@ class QueryAjaxModelLoader(AjaxModelLoader):
criteria = None
for field in self.fields:
for field in self._cached_fields:
flt = {u'%s__icontains' % field.name: term}
if not criteria:
......@@ -47,7 +68,7 @@ class QueryAjaxModelLoader(AjaxModelLoader):
return query.limit(limit).all()
def create_ajax_loader(model, name, field_name, fields):
def create_ajax_loader(model, name, field_name, opts):
prop = getattr(model, field_name, None)
if prop is None:
......@@ -56,20 +77,7 @@ def create_ajax_loader(model, name, field_name, fields):
# TODO: Check for field
remote_model = prop.document_type
remote_fields = []
for field in fields:
if isinstance(field, string_types):
attr = getattr(remote_model, field, None)
if not attr:
raise ValueError('%s.%s does not exist.' % (remote_model, field))
remote_fields.append(attr)
else:
remote_fields.append(field)
return QueryAjaxModelLoader(name, remote_model, remote_fields)
return QueryAjaxModelLoader(name, remote_model, **opts)
def process_ajax_references(references, view):
......@@ -95,7 +103,7 @@ def process_ajax_references(references, view):
for field_name, opts in iteritems(ajax_refs):
child_name = make_name(base, field_name)
if isinstance(opts, (list, tuple)):
if isinstance(opts, dict):
loader = create_ajax_loader(field.document_type_obj, child_name, field_name, opts)
else:
loader = opts
......
......@@ -364,8 +364,8 @@ class ModelView(BaseModelView):
return form_class
# AJAX foreignkey support
def _create_ajax_loader(self, name, fields):
return create_ajax_loader(self.model, name, name, fields)
def _create_ajax_loader(self, name, opts):
return create_ajax_loader(self.model, name, name, opts)
def get_query(self):
"""
......
......@@ -5,19 +5,41 @@ from .tools import get_primary_key
class QueryAjaxModelLoader(AjaxModelLoader):
def __init__(self, name, model, fields):
def __init__(self, name, model, **options):
"""
Constructor.
:param fields:
Fields to run query against
"""
super(QueryAjaxModelLoader, self).__init__(name)
super(QueryAjaxModelLoader, self).__init__(name, options)
self.model = model
self.fields = fields
self.fields = options.get('fields')
if not self.fields:
raise ValueError('AJAX loading requires `fields` to be specified for %s.%s' % (model, self.name))
self._cached_fields = self._process_fields()
self.pk = get_primary_key(model)
def _process_fields(self):
remote_fields = []
for field in self.fields:
if isinstance(field, string_types):
attr = getattr(self.model, field, None)
if not attr:
raise ValueError('%s.%s does not exist.' % (self.model, field))
remote_fields.append(attr)
else:
remote_fields.append(field)
return remote_fields
def format(self, model):
if not model:
return None
......@@ -31,7 +53,7 @@ class QueryAjaxModelLoader(AjaxModelLoader):
query = self.model.select()
stmt = None
for field in self.fields:
for field in self._cached_fields:
q = field ** (u'%%%s%%' % term)
if stmt is None:
......@@ -47,7 +69,7 @@ class QueryAjaxModelLoader(AjaxModelLoader):
return list(query.limit(limit).execute())
def create_ajax_loader(model, name, field_name, fields):
def create_ajax_loader(model, name, field_name, options):
prop = getattr(model, field_name, None)
if prop is None:
......@@ -55,17 +77,4 @@ def create_ajax_loader(model, name, field_name, fields):
# TODO: Check for field
remote_model = prop.rel_model
remote_fields = []
for field in fields:
if isinstance(field, string_types):
attr = getattr(remote_model, field, None)
if not attr:
raise ValueError('%s.%s does not exist.' % (remote_model, field))
remote_fields.append(attr)
else:
remote_fields.append(field)
return QueryAjaxModelLoader(name, remote_model, remote_fields)
return QueryAjaxModelLoader(name, remote_model, **options)
......@@ -13,7 +13,7 @@ from flask.ext.admin.contrib.peewee import filters
from .form import get_form, CustomModelConverter, InlineModelConverter, save_inline
from .tools import get_primary_key, parse_like_term
from .ajax import QueryAjaxModelLoader, create_ajax_loader
from .ajax import create_ajax_loader
class ModelView(BaseModelView):
......@@ -243,8 +243,8 @@ class ModelView(BaseModelView):
return form_class
# AJAX foreignkey support
def _create_ajax_loader(self, name, fields):
return create_ajax_loader(self.model, name, name, fields)
def _create_ajax_loader(self, name, options):
return create_ajax_loader(self.model, name, name, options)
def _handle_join(self, query, field, joins):
if field.model_class != self.model:
......
......@@ -5,7 +5,7 @@ from flask.ext.admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE
class QueryAjaxModelLoader(AjaxModelLoader):
def __init__(self, name, session, model, options):
def __init__(self, name, session, model, **options):
"""
Constructor.
......@@ -74,4 +74,4 @@ def create_ajax_loader(model, session, name, field_name, options):
raise ValueError('%s.%s is not a relation.' % (model, field_name))
remote_model = attr.prop.mapper.class_
return QueryAjaxModelLoader(name, session, remote_model, options)
return QueryAjaxModelLoader(name, session, remote_model, **options)
......@@ -384,7 +384,7 @@ class BaseModelView(BaseView, ActionsMixin):
class MyModelView(BaseModelView):
form_ajax_refs = {
'user': QueryAjaxModelLoader('user', db.session, User, page_size=10)
'user': QueryAjaxModelLoader('user', db.session, User, fields=['email'], page_size=10)
}
If you need custom loading functionality, you can implement your custom loading behavior
......
......@@ -375,7 +375,9 @@ def test_ajax_fk():
Model2,
url='view',
form_ajax_refs={
'model1': ('test1', 'test2')
'model1': {
'fields': ('test1', 'test2')
}
}
)
admin.add_view(view)
......@@ -448,7 +450,9 @@ def test_nested_ajax_refs():
form_subdocuments = {
'nested': {
'form_ajax_refs': {
'comment': ['name']
'comment': {
'fields': ['name']
}
}
}
}
......
......@@ -220,7 +220,9 @@ def test_ajax_fk():
Model2,
url='view',
form_ajax_refs={
'model1': ('test1', 'test2')
'model1': {
'fields': ('test1', 'test2')
}
}
)
admin.add_view(view)
......
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