Commit 9236dd87 authored by Serge S. Koval's avatar Serge S. Koval

AJAX FK support in inline Peewee models

parent 0c2f226a
import mongoengine
from flask.ext.admin._compat import as_unicode
from flask.ext.admin._compat import as_unicode, string_types
from flask.ext.admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE
from .tools import get_primary_key
......@@ -47,3 +45,27 @@ class QueryAjaxModelLoader(AjaxModelLoader):
query = query.offset(offset)
return list(query.limit(limit).execute())
def create_ajax_loader(model, name, field_name, fields):
prop = getattr(model, field_name, None)
if prop is None:
raise ValueError('Model %s does not have field %s.' % (model, field_name))
# 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)
......@@ -11,6 +11,7 @@ from flask.ext.admin.model.form import InlineFormAdmin, InlineModelConverterBase
from flask.ext.admin.model.fields import InlineModelFormField, InlineFieldList, AjaxSelectField
from .tools import get_primary_key
from .ajax import create_ajax_loader
class InlineModelFormList(InlineFieldList):
......@@ -90,7 +91,7 @@ class CustomModelConverter(ModelConverter):
self.converters[TimeField] = self.handle_time
def handle_foreign_key(self, model, field, **kwargs):
loader = self.view._form_ajax_refs.get(field.name)
loader = getattr(self.view, '_form_ajax_refs', {}).get(field.name)
if loader:
if field.null:
......@@ -173,8 +174,31 @@ class InlineModelConverter(InlineModelConverterBase):
info = InlineFormAdmin(model, **attrs)
# Resolve AJAX FKs
info._form_ajax_refs = self.process_ajax_refs(info)
return info
def process_ajax_refs(self, info):
refs = getattr(info, 'form_ajax_refs', None)
result = {}
if refs:
for name, opts in iteritems(refs):
new_name = '%s.%s' % (info.model.__name__.lower(), name)
loader = None
if isinstance(opts, (list, tuple)):
loader = create_ajax_loader(info.model, new_name, name, opts)
else:
loader = opts
result[name] = loader
self.view._form_ajax_refs[new_name] = loader
return result
def contribute(self, converter, model, form_class, inline_model):
# Find property from target model to current model
reverse_field = None
......
......@@ -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
from .ajax import QueryAjaxModelLoader, create_ajax_loader
class ModelView(BaseModelView):
......@@ -244,27 +244,7 @@ class ModelView(BaseModelView):
# AJAX foreignkey support
def _create_ajax_loader(self, name, fields):
prop = getattr(self.model, name, None)
if prop is None:
raise ValueError('Model %s does not have field %s.' % (self.model, name))
# 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 create_ajax_loader(self.model, name, name, fields)
def _handle_join(self, query, field, joins):
if field.model_class != self.model:
......
......@@ -508,7 +508,6 @@ class InlineModelConverter(InlineModelConverterBase):
return result
def contribute(self, model, form_class, inline_model):
"""
Generate form fields for inline forms and contribute them to
......
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