@@ -826,8 +826,7 @@ def inlineformset_factory(document, form=DocumentForm,
826
826
# FormSet.rel_field = rel_field
827
827
# return FormSet
828
828
829
-
830
- class EmbeddedDocumentFormSet (BaseDocumentFormSet ):
829
+ class EmbeddedDocumentFormSet (BaseInlineDocumentFormSet ):
831
830
def __init__ (self , data = None , files = None , instance = None ,
832
831
save_as_new = False , prefix = None , queryset = [], parent_document = None , ** kwargs ):
833
832
self .parent_document = parent_document
@@ -838,6 +837,17 @@ def _construct_form(self, i, **kwargs):
838
837
defaults .update (kwargs )
839
838
form = super (EmbeddedDocumentFormSet , self )._construct_form (i , ** defaults )
840
839
return form
840
+
841
+ @property
842
+ def empty_form (self ):
843
+ form = self .form (
844
+ self .parent_document ,
845
+ auto_id = self .auto_id ,
846
+ prefix = self .add_prefix ('__prefix__' ),
847
+ empty_permitted = True ,
848
+ )
849
+ self .add_fields (form , None )
850
+ return form
841
851
842
852
def save (self , commit = True ):
843
853
# Don't try to save the new documents. Embedded objects don't have
@@ -846,8 +856,22 @@ def save(self, commit=True):
846
856
847
857
if commit and self .parent_document is not None :
848
858
form = self .empty_form
849
- attr_data = getattr (self .parent_document , form ._meta .embedded_field , [])
850
- setattr (self .parent_document , form ._meta .embedded_field , attr_data + objs )
859
+ # The thing about formsets is that the base use case is to edit *all*
860
+ # of the associated objects on a model. As written, using these FormSets this
861
+ # way will cause the existing embedded documents to get saved along with a
862
+ # copy of themselves plus any new ones you added.
863
+ #
864
+ # The only way you could do "updates" of existing embedded document fields is
865
+ # if those embedded documents had ObjectIDs of their own, which they don't
866
+ # by default in Mongoengine.
867
+ #
868
+ # In this case it makes the most sense to simply replace the embedded field
869
+ # with the new values gathered form the formset, rather than adding the new
870
+ # values to the existing values, because the new values will almost always
871
+ # contain the old values (with the default use case.)
872
+ #
873
+ # attr_data = getattr(self.parent_document, form._meta.embedded_field, [])
874
+ setattr (self .parent_document , form ._meta .embedded_field , objs or [])
851
875
self .parent_document .save ()
852
876
853
877
return objs
0 commit comments