Commit 7a4d2b7b authored by Serge S. Koval's avatar Serge S. Koval

Added MongoEngine subdocument pre-caching

parent 5202791f
import mongoengine
from flask.ext.admin._compat import as_unicode
from flask.ext.admin._compat import string_types, as_unicode
from flask.ext.admin.model.ajax import AjaxModelLoader, DEFAULT_PAGE_SIZE
......@@ -45,3 +45,28 @@ class QueryAjaxModelLoader(AjaxModelLoader):
query = query.skip(offset)
return query.limit(limit).all()
def create_ajax_loader(model, name, fields):
prop = getattr(model, name, None)
if prop is None:
raise ValueError('Model %s does not have field %s.' % (model, name))
# 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)
......@@ -5,16 +5,13 @@ from wtforms import fields, validators
from flask.ext.mongoengine.wtf import orm, fields as mongo_fields
from flask.ext.admin import form
from flask.ext.admin.model.form import FieldPlaceholder, InlineBaseFormAdmin
from flask.ext.admin.model.fields import InlineFieldList, AjaxSelectField, AjaxSelectMultipleField
from flask.ext.admin.model.form import FieldPlaceholder
from flask.ext.admin.model.fields import InlineFieldList, AjaxSelectField
from flask.ext.admin.model.widgets import InlineFormWidget
from flask.ext.admin._compat import iteritems
from .fields import ModelFormField, MongoFileField, MongoImageField
class EmbeddedForm(InlineBaseFormAdmin):
pass
from .subdoc import EmbeddedForm
class CustomModelConverter(orm.ModelConverter):
......@@ -39,19 +36,14 @@ class CustomModelConverter(orm.ModelConverter):
return None
def _get_subdocument_config(self, name):
config = getattr(self.view, 'form_subdocuments', {})
config = getattr(self.view, '_form_subdocuments', {})
p = config.get(name)
if not p:
return EmbeddedForm()
if isinstance(p, dict):
return EmbeddedForm(**p)
elif isinstance(p, EmbeddedForm):
return p
raise ValueError('Invalid subdocument type: expecting dict or instance of flask.ext.admin.contrib.mongoengine.EmbeddedForm, got %s' % type(p))
def clone_converter(self, view):
return self.__class__(view)
......
......@@ -18,7 +18,8 @@ from .form import get_form, CustomModelConverter
from .typefmt import DEFAULT_FORMATTERS
from .tools import parse_like_term
from .helpers import format_error
from .ajax import QueryAjaxModelLoader
from .ajax import QueryAjaxModelLoader, create_ajax_loader
from .subdoc import convert_subdocuments
SORTABLE_FIELDS = set((
......@@ -98,7 +99,7 @@ class ModelView(BaseModelView):
List of allowed search field types.
"""
form_subdocuments = {}
form_subdocuments = None
"""
Subdocument configuration options.
......@@ -199,6 +200,16 @@ class ModelView(BaseModelView):
self._primary_key = self.scaffold_pk()
def _refresh_cache(self):
# Process subdocuments
if self.form_subdocuments is None:
self.form_subdocuments = {}
self._form_subdocuments = convert_subdocuments(self.form_subdocuments)
# Cache other properties
super(ModelView, self)._refresh_cache()
def _get_model_fields(self, model=None):
"""
Inspect model and return list of model fields
......@@ -339,28 +350,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.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 create_ajax_loader(self.model, name, fields)
def get_query(self):
"""
......
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