Skip to content

Commit

Permalink
Make sure not to use LazyDocumentMetaWrapper as doc's meta for #61
Browse files Browse the repository at this point in the history
  • Loading branch information
jschrewe committed Nov 21, 2013
1 parent 703965c commit 21fb038
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 30 deletions.
41 changes: 29 additions & 12 deletions mongodbforms/documentoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def to(self, value):


class PkWrapper(object):
editable = False
fake = False

def __init__(self, wrapped):
self.obj = wrapped

Expand Down Expand Up @@ -118,6 +121,8 @@ class DocumentMetaWrapper(MutableMapping):
_meta = None
concrete_model = None
concrete_managers = []
virtual_fields = []
auto_created = False

def __init__(self, document, meta=None):
super(DocumentMetaWrapper, self).__init__()
Expand All @@ -127,9 +132,10 @@ def __init__(self, document, meta=None):
# here for now always the document
self.concrete_model = document
if meta is None:
self._meta = getattr(document, '_meta', {})
else:
self._meta = meta
meta = getattr(document, '_meta', {})
if isinstance(meta, LazyDocumentMetaWrapper):
meta = meta._meta
self._meta = meta

try:
self.object_name = self.document.__name__
Expand All @@ -143,9 +149,9 @@ def __init__(self, document, meta=None):
self._setup_document_fields()
# Setup self.pk if the document has an id_field in it's meta
# if it doesn't have one it's an embedded document
if 'id_field' in self._meta:
self.pk_name = self._meta['id_field']
self._init_pk()
#if 'id_field' in self._meta:
# self.pk_name = self._meta['id_field']
self._init_pk()

def _setup_document_fields(self):
for f in self.document._fields.values():
Expand Down Expand Up @@ -183,16 +189,27 @@ def _init_pk(self):
The function also adds a _get_pk_val method to the document.
"""
pk_field = getattr(self.document, self.pk_name)
if 'id_field' in self._meta:
self.pk_name = self._meta['id_field']
pk_field = getattr(self.document, self.pk_name)
else:
pk_field = None
self.pk = PkWrapper(pk_field)
self.pk.name = self.pk_name
self.pk.attname = self.pk_name

self.document._pk_val = pk_field

def _get_pk_val(self):
return self._pk_val
patch_document(_get_pk_val, self.document)

if pk_field is not None:
self.pk.name = self.pk_name
self.pk.attname = self.pk_name
self.document._pk_val = pk_field
patch_document(_get_pk_val, self.document)
else:
self.pk.fake = True
# this is used in the admin and used to determine if the admin
# needs to add a hidden pk field. It does not for embedded fields.
# So we pretend to have an editable pk field and just ignore it otherwise
self.pk.editable = True

@property
def app_label(self):
Expand Down
36 changes: 18 additions & 18 deletions mongodbforms/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,13 @@ def inlineformset_factory(document, form=DocumentForm,
class EmbeddedDocumentFormSet(BaseDocumentFormSet):
def __init__(self, data=None, files=None, save_as_new=False,
prefix=None, queryset=[], parent_document=None, **kwargs):
self.parent_document = parent_document
if parent_document is not None:
self.parent_document = parent_document

if 'instance' in kwargs:
instance = kwargs.pop('instance')
if parent_document is None:
self.parent_document = instance

queryset = getattr(self.parent_document,
self.form._meta.embedded_field)
Expand All @@ -848,7 +854,8 @@ def _construct_form(self, i, **kwargs):
# a huge amount of time iterating over the list field on form __init__
emb_list = getattr(self.parent_document,
self.form._meta.embedded_field)
if emb_list is not None and len(emb_list) < i:

if emb_list is not None and len(emb_list) > i:
defaults['position'] = i
defaults.update(kwargs)

Expand Down Expand Up @@ -878,22 +885,15 @@ def save(self, commit=True):
objs = objs or []

if commit and self.parent_document is not None:
# The thing about formsets is that the base use case is to edit
# *all* of the associated objects on a model. As written, using
# these FormSets this way will cause the existing embedded
# documents to get saved along with a copy of themselves plus any
# new ones you added.
#
# The only way you could do "updates" of existing embedded document
# fields is if those embedded documents had ObjectIDs of their own,
# which they don't by default in Mongoengine.
#
# In this case it makes the most sense to simply replace the
# embedded field with the new values gathered form the formset,
# rather than adding the new values to the existing values, because
# the new values will almost always contain the old values (with
# the default use case.)
setattr(self.parent_document, self.form._meta.embedded_field, objs)
field = self.parent_document._fields.get(self.form._meta.embedded_field, None)
if isinstance(field, EmbeddedDocumentField):
try:
obj = objs[0]
except IndexError:
obj = None
setattr(self.parent_document, self.form._meta.embedded_field, obj)
else:
setattr(self.parent_document, self.form._meta.embedded_field, objs)
self.parent_document.save()

return objs
Expand Down

0 comments on commit 21fb038

Please sign in to comment.