Skip to content

Commit 6c9e179

Browse files
bbenne10Bryan Bennett
authored andcommitted
MongoEngine/mongoengine MongoEngine#1217: Curry **kwargs through to_mongo on fields
1 parent decd70e commit 6c9e179

File tree

5 files changed

+58
-46
lines changed

5 files changed

+58
-46
lines changed

mongoengine/base/document.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -325,20 +325,17 @@ def to_mongo(self, use_db_field=True, fields=None):
325325

326326
if value is not None:
327327

328-
if isinstance(field, EmbeddedDocumentField):
329-
if fields:
330-
key = '%s.' % field_name
331-
embedded_fields = [
332-
i.replace(key, '') for i in fields
333-
if i.startswith(key)]
328+
if fields:
329+
key = '%s.' % field_name
330+
embedded_fields = [
331+
i.replace(key, '') for i in fields
332+
if i.startswith(key)]
334333

335-
else:
336-
embedded_fields = []
337-
338-
value = field.to_mongo(value, use_db_field=use_db_field,
339-
fields=embedded_fields)
340334
else:
341-
value = field.to_mongo(value)
335+
embedded_fields = []
336+
337+
value = field.to_mongo(value, use_db_field=use_db_field,
338+
fields=embedded_fields)
342339

343340
# Handle self generating fields
344341
if value is None and field._auto_gen:

mongoengine/base/fields.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def to_python(self, value):
158158
"""
159159
return value
160160

161-
def to_mongo(self, value):
161+
def to_mongo(self, value, **kwargs):
162162
"""Convert a Python type to a MongoDB-compatible type.
163163
"""
164164
return self.to_python(value)
@@ -325,7 +325,7 @@ def to_python(self, value):
325325
key=operator.itemgetter(0))]
326326
return value_dict
327327

328-
def to_mongo(self, value):
328+
def to_mongo(self, value, **kwargs):
329329
"""Convert a Python type to a MongoDB-compatible type.
330330
"""
331331
Document = _import_class("Document")
@@ -337,9 +337,10 @@ def to_mongo(self, value):
337337

338338
if hasattr(value, 'to_mongo'):
339339
if isinstance(value, Document):
340-
return GenericReferenceField().to_mongo(value)
340+
return GenericReferenceField().to_mongo(
341+
value, **kwargs)
341342
cls = value.__class__
342-
val = value.to_mongo()
343+
val = value.to_mongo(**kwargs)
343344
# If it's a document that is not inherited add _cls
344345
if isinstance(value, EmbeddedDocument):
345346
val['_cls'] = cls.__name__
@@ -354,7 +355,7 @@ def to_mongo(self, value):
354355
return value
355356

356357
if self.field:
357-
value_dict = dict([(key, self.field.to_mongo(item))
358+
value_dict = dict([(key, self.field.to_mongo(item, **kwargs))
358359
for key, item in value.iteritems()])
359360
else:
360361
value_dict = {}
@@ -373,19 +374,20 @@ def to_mongo(self, value):
373374
meta.get('allow_inheritance', ALLOW_INHERITANCE)
374375
is True)
375376
if not allow_inheritance and not self.field:
376-
value_dict[k] = GenericReferenceField().to_mongo(v)
377+
value_dict[k] = GenericReferenceField().to_mongo(
378+
v, **kwargs)
377379
else:
378380
collection = v._get_collection_name()
379381
value_dict[k] = DBRef(collection, v.pk)
380382
elif hasattr(v, 'to_mongo'):
381383
cls = v.__class__
382-
val = v.to_mongo()
384+
val = v.to_mongo(**kwargs)
383385
# If it's a document that is not inherited add _cls
384386
if isinstance(v, (Document, EmbeddedDocument)):
385387
val['_cls'] = cls.__name__
386388
value_dict[k] = val
387389
else:
388-
value_dict[k] = self.to_mongo(v)
390+
value_dict[k] = self.to_mongo(v, **kwargs)
389391

390392
if is_list: # Convert back to a list
391393
return [v for _, v in sorted(value_dict.items(),
@@ -443,7 +445,7 @@ def to_python(self, value):
443445
pass
444446
return value
445447

446-
def to_mongo(self, value):
448+
def to_mongo(self, value, **kwargs):
447449
if not isinstance(value, ObjectId):
448450
try:
449451
return ObjectId(unicode(value))
@@ -618,7 +620,7 @@ def _validate_multipolygon(self, value):
618620
if errors:
619621
return "Invalid MultiPolygon:\n%s" % ", ".join(errors)
620622

621-
def to_mongo(self, value):
623+
def to_mongo(self, value, **kwargs):
622624
if isinstance(value, dict):
623625
return value
624626
return SON([("type", self._type), ("coordinates", value)])

mongoengine/fields.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ def to_python(self, value):
325325
return value
326326
return value.quantize(decimal.Decimal(".%s" % ("0" * self.precision)), rounding=self.rounding)
327327

328-
def to_mongo(self, value, use_db_field=True):
328+
def to_mongo(self, value, **kwargs):
329329
if value is None:
330330
return value
331331
if self.force_string:
@@ -388,7 +388,7 @@ def validate(self, value):
388388
if not isinstance(new_value, (datetime.datetime, datetime.date)):
389389
self.error(u'cannot parse date "%s"' % value)
390390

391-
def to_mongo(self, value):
391+
def to_mongo(self, value, **kwargs):
392392
if value is None:
393393
return value
394394
if isinstance(value, datetime.datetime):
@@ -511,7 +511,7 @@ def to_python(self, value):
511511
except:
512512
return original_value
513513

514-
def to_mongo(self, value):
514+
def to_mongo(self, value, **kwargs):
515515
value = self.to_python(value)
516516
return self._convert_from_datetime(value)
517517

@@ -546,11 +546,10 @@ def to_python(self, value):
546546
return self.document_type._from_son(value, _auto_dereference=self._auto_dereference)
547547
return value
548548

549-
def to_mongo(self, value, use_db_field=True, fields=[]):
549+
def to_mongo(self, value, **kwargs):
550550
if not isinstance(value, self.document_type):
551551
return value
552-
return self.document_type.to_mongo(value, use_db_field,
553-
fields=fields)
552+
return self.document_type.to_mongo(value, **kwargs)
554553

555554
def validate(self, value, clean=True):
556555
"""Make sure that the document instance is an instance of the
@@ -600,11 +599,11 @@ def validate(self, value, clean=True):
600599

601600
value.validate(clean=clean)
602601

603-
def to_mongo(self, document, use_db_field=True):
602+
def to_mongo(self, document, **kwargs):
604603
if document is None:
605604
return None
606605

607-
data = document.to_mongo(use_db_field)
606+
data = document.to_mongo(**kwargs)
608607
if '_cls' not in data:
609608
data['_cls'] = document._class_name
610609
return data
@@ -616,7 +615,7 @@ class DynamicField(BaseField):
616615
617616
Used by :class:`~mongoengine.DynamicDocument` to handle dynamic data"""
618617

619-
def to_mongo(self, value):
618+
def to_mongo(self, value, **kwargs):
620619
"""Convert a Python type to a MongoDB compatible type.
621620
"""
622621

@@ -625,7 +624,7 @@ def to_mongo(self, value):
625624

626625
if hasattr(value, 'to_mongo'):
627626
cls = value.__class__
628-
val = value.to_mongo()
627+
val = value.to_mongo(**kwargs)
629628
# If we its a document thats not inherited add _cls
630629
if isinstance(value, Document):
631630
val = {"_ref": value.to_dbref(), "_cls": cls.__name__}
@@ -643,7 +642,7 @@ def to_mongo(self, value):
643642

644643
data = {}
645644
for k, v in value.iteritems():
646-
data[k] = self.to_mongo(v)
645+
data[k] = self.to_mongo(v, **kwargs)
647646

648647
value = data
649648
if is_list: # Convert back to a list
@@ -755,8 +754,8 @@ def __init__(self, field, **kwargs):
755754
self._order_reverse = kwargs.pop('reverse')
756755
super(SortedListField, self).__init__(field, **kwargs)
757756

758-
def to_mongo(self, value):
759-
value = super(SortedListField, self).to_mongo(value)
757+
def to_mongo(self, value, **kwargs):
758+
value = super(SortedListField, self).to_mongo(value, **kwargs)
760759
if self._ordering is not None:
761760
return sorted(value, key=itemgetter(self._ordering),
762761
reverse=self._order_reverse)
@@ -942,7 +941,7 @@ def __get__(self, instance, owner):
942941

943942
return super(ReferenceField, self).__get__(instance, owner)
944943

945-
def to_mongo(self, document):
944+
def to_mongo(self, document, **kwargs):
946945
if isinstance(document, DBRef):
947946
if not self.dbref:
948947
return document.id
@@ -965,7 +964,7 @@ def to_mongo(self, document):
965964
id_field_name = cls._meta['id_field']
966965
id_field = cls._fields[id_field_name]
967966

968-
id_ = id_field.to_mongo(id_)
967+
id_ = id_field.to_mongo(id_, **kwargs)
969968
if self.document_type._meta.get('abstract'):
970969
collection = cls._get_collection_name()
971970
return DBRef(collection, id_, cls=cls._class_name)
@@ -1088,7 +1087,7 @@ def __get__(self, instance, owner):
10881087

10891088
return super(CachedReferenceField, self).__get__(instance, owner)
10901089

1091-
def to_mongo(self, document):
1090+
def to_mongo(self, document, **kwargs):
10921091
id_field_name = self.document_type._meta['id_field']
10931092
id_field = self.document_type._fields[id_field_name]
10941093

@@ -1103,10 +1102,11 @@ def to_mongo(self, document):
11031102
# TODO: should raise here or will fail next statement
11041103

11051104
value = SON((
1106-
("_id", id_field.to_mongo(id_)),
1105+
("_id", id_field.to_mongo(id_, **kwargs)),
11071106
))
11081107

1109-
value.update(dict(document.to_mongo(fields=self.fields)))
1108+
kwargs['fields'] = self.fields
1109+
value.update(dict(document.to_mongo(**kwargs)))
11101110
return value
11111111

11121112
def prepare_query_value(self, op, value):
@@ -1222,7 +1222,7 @@ def dereference(self, value):
12221222
doc = doc_cls._from_son(doc)
12231223
return doc
12241224

1225-
def to_mongo(self, document, use_db_field=True):
1225+
def to_mongo(self, document, **kwargs):
12261226
if document is None:
12271227
return None
12281228

@@ -1241,7 +1241,7 @@ def to_mongo(self, document, use_db_field=True):
12411241
else:
12421242
id_ = document
12431243

1244-
id_ = id_field.to_mongo(id_)
1244+
id_ = id_field.to_mongo(id_, **kwargs)
12451245
collection = document._get_collection_name()
12461246
ref = DBRef(collection, id_)
12471247
return SON((
@@ -1270,7 +1270,7 @@ def __set__(self, instance, value):
12701270
value = bin_type(value)
12711271
return super(BinaryField, self).__set__(instance, value)
12721272

1273-
def to_mongo(self, value):
1273+
def to_mongo(self, value, **kwargs):
12741274
return Binary(value)
12751275

12761276
def validate(self, value):
@@ -1495,7 +1495,7 @@ def get_proxy_obj(self, key, instance, db_alias=None, collection_name=None):
14951495
db_alias=db_alias,
14961496
collection_name=collection_name)
14971497

1498-
def to_mongo(self, value):
1498+
def to_mongo(self, value, **kwargs):
14991499
# Store the GridFS file id in MongoDB
15001500
if isinstance(value, self.proxy_class) and value.grid_id is not None:
15011501
return value.grid_id
@@ -1845,7 +1845,7 @@ def to_python(self, value):
18451845
return original_value
18461846
return value
18471847

1848-
def to_mongo(self, value):
1848+
def to_mongo(self, value, **kwargs):
18491849
if not self._binary:
18501850
return unicode(value)
18511851
elif isinstance(value, basestring):

tests/document/instance.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,19 @@ class Doc(Document):
679679
doc = Doc.objects.get()
680680
self.assertHasInstance(doc.embedded_field[0], doc)
681681

682+
def test_embedded_document_complex_instance_no_use_db_field(self):
683+
"""Ensure that use_db_field is propagated to list of Emb Docs
684+
"""
685+
class Embedded(EmbeddedDocument):
686+
string = StringField(db_field='s')
687+
688+
class Doc(Document):
689+
embedded_field = ListField(EmbeddedDocumentField(Embedded))
690+
691+
d = Doc(embedded_field=[Embedded(string="Hi")]).to_mongo(
692+
use_db_field=False).to_dict()
693+
self.assertEqual(d['embedded_field'], [{'string': 'Hi'}])
694+
682695
def test_instance_is_set_on_setattr(self):
683696

684697
class Email(EmbeddedDocument):

tests/fields/fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3380,7 +3380,7 @@ class EnumField(BaseField):
33803380
def __init__(self, **kwargs):
33813381
super(EnumField, self).__init__(**kwargs)
33823382

3383-
def to_mongo(self, value):
3383+
def to_mongo(self, value, **kwargs):
33843384
return value
33853385

33863386
def to_python(self, value):

0 commit comments

Comments
 (0)