Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mongoengine/base/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ def _from_son(cls, son, _auto_dereference=True, only_fields=None, created=False)

fields = cls._fields
if not _auto_dereference:
fields = copy.copy(fields)
fields = copy.deepcopy(fields)

for field_name, field in fields.iteritems():
field._auto_dereference = _auto_dereference
Expand Down
8 changes: 5 additions & 3 deletions mongoengine/base/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,15 @@ def __get__(self, instance, owner):
ReferenceField = _import_class('ReferenceField')
GenericReferenceField = _import_class('GenericReferenceField')
EmbeddedDocumentListField = _import_class('EmbeddedDocumentListField')
dereference = (self._auto_dereference and

auto_dereference = instance._fields[self.name]._auto_dereference

dereference = (auto_dereference and
(self.field is None or isinstance(self.field,
(GenericReferenceField, ReferenceField))))

_dereference = _import_class('DeReference')()

self._auto_dereference = instance._fields[self.name]._auto_dereference
if instance._initialised and dereference and instance._data.get(self.name):
instance._data[self.name] = _dereference(
instance._data.get(self.name), max_depth=1, instance=instance,
Expand All @@ -293,7 +295,7 @@ def __get__(self, instance, owner):
value = BaseDict(value, instance, self.name)
instance._data[self.name] = value

if (self._auto_dereference and instance._initialised and
if (auto_dereference and instance._initialised and
isinstance(value, (BaseList, BaseDict)) and
not value._dereferenced):
value = _dereference(
Expand Down
5 changes: 3 additions & 2 deletions mongoengine/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -1104,9 +1104,9 @@ def __get__(self, instance, owner):

# Get value from document instance if available
value = instance._data.get(self.name)
self._auto_dereference = instance._fields[self.name]._auto_dereference
auto_dereference = instance._fields[self.name]._auto_dereference
# Dereference DBRefs
if self._auto_dereference and isinstance(value, DBRef):
if auto_dereference and isinstance(value, DBRef):
if hasattr(value, 'cls'):
# Dereference using the class type specified in the reference
cls = get_document(value.cls)
Expand Down Expand Up @@ -1267,6 +1267,7 @@ def __get__(self, instance, owner):
# Get value from document instance if available
value = instance._data.get(self.name)
self._auto_dereference = instance._fields[self.name]._auto_dereference

# Dereference DBRefs
if self._auto_dereference and isinstance(value, DBRef):
dereferenced = self.document_type._get_db().dereference(value)
Expand Down
84 changes: 74 additions & 10 deletions tests/queryset/queryset.py
Original file line number Diff line number Diff line change
Expand Up @@ -4674,11 +4674,69 @@ class User(Document):
User(name="Bob Dole", organization=whitehouse).save()

qs = User.objects()
qs_user = qs.first()

self.assertIsInstance(qs.first().organization, Organization)
self.assertNotIsInstance(qs.no_dereference().first().organization, Organization)
self.assertNotIsInstance(qs.no_dereference().get().organization, Organization)

self.assertIsInstance(qs.no_dereference().first().organization, DBRef)

self.assertIsInstance(qs_user.organization, Organization)
self.assertIsInstance(qs.first().organization, Organization)

def test_no_dereference_internals(self):
# Test the internals on which queryset.no_dereference relies on
class Organization(Document):
name = StringField()

class User(Document):
organization = ReferenceField(Organization)

User.drop_collection()
Organization.drop_collection()

cls_organization_field = User.organization
self.assertTrue(cls_organization_field._auto_dereference, True) # default

org = Organization(name="whatever").save()
User(organization=org).save()

qs_no_deref = User.objects().no_dereference()
user_no_deref = qs_no_deref.first()
self.assertFalse(qs_no_deref._auto_dereference)

# Make sure the instance field is different from the class field
instance_org_field = user_no_deref._fields['organization']
self.assertIsNot(instance_org_field, cls_organization_field)
self.assertFalse(instance_org_field._auto_dereference)

self.assertIsInstance(user_no_deref.organization, DBRef)
self.assertTrue(cls_organization_field._auto_dereference, True) # Make sure the class Field wasn't altered

def test_no_dereference_no_side_effect_on_existing_instance(self):
# Relates to issue #1677 - ensures no regression of the bug

class Organization(Document):
name = StringField()

class User(Document):
organization = ReferenceField(Organization)

User.drop_collection()
Organization.drop_collection()

org = Organization(name="whatever").save()
User(organization=org).save()

qs = User.objects()
user = qs.first()

qs_no_deref = User.objects().no_dereference()
user_no_deref = qs_no_deref.first()

no_derf_org = user_no_deref.organization # was triggering the bug
self.assertIsInstance(no_derf_org, DBRef)
self.assertIsInstance(user.organization, Organization)

def test_no_dereference_embedded_doc(self):

class User(Document):
Expand All @@ -4693,7 +4751,7 @@ class Organization(Document):
members = ListField(EmbeddedDocumentField(Member))
ceo = ReferenceField(User)
member = EmbeddedDocumentField(Member)
admin = ListField(ReferenceField(User))
admins = ListField(ReferenceField(User))

Organization.drop_collection()
User.drop_collection()
Expand All @@ -4703,16 +4761,22 @@ class Organization(Document):

member = Member(name="Flash", user=user)

company = Organization(name="Mongo Inc", ceo=user, member=member)
company.admin.append(user)
company.members.append(member)
company = Organization(name="Mongo Inc",
ceo=user,
member=member,
admins=[user],
members=[member])
company.save()

result = Organization.objects().no_dereference().first()
org = Organization.objects().no_dereference().first()

self.assertNotEqual(id(org._fields['admins']), id(Organization.admins))
self.assertFalse(org._fields['admins']._auto_dereference)

self.assertIsInstance(result.admin[0], (DBRef, ObjectId))
self.assertIsInstance(result.member.user, (DBRef, ObjectId))
self.assertIsInstance(result.members[0].user, (DBRef, ObjectId))
admin = org.admins[0]
self.assertIsInstance(admin, DBRef)
self.assertIsInstance(org.member.user, DBRef)
self.assertIsInstance(org.members[0].user, DBRef)

def test_cached_queryset(self):
class Person(Document):
Expand Down