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, string_types
from flask.ext.admin._compat import as_unicode
from flask.ext.admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE from flask.ext.admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE
from .tools import get_primary_key from .tools import get_primary_key
...@@ -47,3 +45,27 @@ class QueryAjaxModelLoader(AjaxModelLoader): ...@@ -47,3 +45,27 @@ class QueryAjaxModelLoader(AjaxModelLoader):
query = query.offset(offset) query = query.offset(offset)
return list(query.limit(limit).execute()) 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 ...@@ -11,6 +11,7 @@ from flask.ext.admin.model.form import InlineFormAdmin, InlineModelConverterBase
from flask.ext.admin.model.fields import InlineModelFormField, InlineFieldList, AjaxSelectField from flask.ext.admin.model.fields import InlineModelFormField, InlineFieldList, AjaxSelectField
from .tools import get_primary_key from .tools import get_primary_key
from .ajax import create_ajax_loader
class InlineModelFormList(InlineFieldList): class InlineModelFormList(InlineFieldList):
...@@ -90,7 +91,7 @@ class CustomModelConverter(ModelConverter): ...@@ -90,7 +91,7 @@ class CustomModelConverter(ModelConverter):
self.converters[TimeField] = self.handle_time self.converters[TimeField] = self.handle_time
def handle_foreign_key(self, model, field, **kwargs): 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 loader:
if field.null: if field.null:
...@@ -173,8 +174,31 @@ class InlineModelConverter(InlineModelConverterBase): ...@@ -173,8 +174,31 @@ class InlineModelConverter(InlineModelConverterBase):
info = InlineFormAdmin(model, **attrs) info = InlineFormAdmin(model, **attrs)
# Resolve AJAX FKs
info._form_ajax_refs = self.process_ajax_refs(info)
return 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): def contribute(self, converter, model, form_class, inline_model):
# Find property from target model to current model # Find property from target model to current model
reverse_field = None reverse_field = None
......
...@@ -13,7 +13,7 @@ from flask.ext.admin.contrib.peewee import filters ...@@ -13,7 +13,7 @@ from flask.ext.admin.contrib.peewee import filters
from .form import get_form, CustomModelConverter, InlineModelConverter, save_inline from .form import get_form, CustomModelConverter, InlineModelConverter, save_inline
from .tools import get_primary_key, parse_like_term from .tools import get_primary_key, parse_like_term
from .ajax import QueryAjaxModelLoader from .ajax import QueryAjaxModelLoader, create_ajax_loader
class ModelView(BaseModelView): class ModelView(BaseModelView):
...@@ -244,27 +244,7 @@ class ModelView(BaseModelView): ...@@ -244,27 +244,7 @@ class ModelView(BaseModelView):
# AJAX foreignkey support # AJAX foreignkey support
def _create_ajax_loader(self, name, fields): def _create_ajax_loader(self, name, fields):
prop = getattr(self.model, name, None) return create_ajax_loader(self.model, name, name, fields)
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)
def _handle_join(self, query, field, joins): def _handle_join(self, query, field, joins):
if field.model_class != self.model: if field.model_class != self.model:
......
...@@ -508,7 +508,6 @@ class InlineModelConverter(InlineModelConverterBase): ...@@ -508,7 +508,6 @@ class InlineModelConverter(InlineModelConverterBase):
return result return result
def contribute(self, model, form_class, inline_model): def contribute(self, model, form_class, inline_model):
""" """
Generate form fields for inline forms and contribute them to 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