From 8bde0c0e539594db177c37290e76045a9d4ca286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wilson=20J=C3=BAnior?= Date: Mon, 23 Jul 2012 12:31:47 -0300 Subject: [PATCH 1/9] Small fix in SequenceField --- mongoengine/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index ba8ff2dd..42f11ea9 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -1289,7 +1289,7 @@ class SequenceField(IntField): instance._data[self.name] = value instance._mark_as_changed(self.name) - return value + return int(value) if value else None def __set__(self, instance, value): From 8df81571fc41c623b0fffa3da99c37813b8a3edc Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 1 Aug 2012 13:28:28 +0100 Subject: [PATCH 2/9] Fixed FileField comparision Refs hmarr/mongoengine#547 --- docs/changelog.rst | 4 ++ mongoengine/fields.py | 2 + tests/test_fields.py | 126 ++++++++++++++++++++++-------------------- 3 files changed, 73 insertions(+), 59 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 97926f8d..2b52582e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,10 @@ Changelog ========= +Changes in 0.6.X +================ + +- Fixed FileField comparision (hmarr/mongoengine#547) Changes in 0.6.18 ================= diff --git a/mongoengine/fields.py b/mongoengine/fields.py index 94f79a12..89b81cdb 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -907,6 +907,8 @@ class GridFSProxy(object): return '<%s: %s>' % (self.__class__.__name__, self.grid_id) def __cmp__(self, other): + if not isinstance(other, GridFSProxy): + return -1 return cmp((self.grid_id, self.collection_name, self.db_alias), (other.grid_id, other.collection_name, other.db_alias)) diff --git a/tests/test_fields.py b/tests/test_fields.py index 72972cc4..4e708563 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1567,13 +1567,13 @@ class FieldTest(unittest.TestCase): """Ensure that file fields can be written to and their data retrieved """ class PutFile(Document): - file = FileField() + the_file = FileField() class StreamFile(Document): - file = FileField() + the_file = FileField() class SetFile(Document): - file = FileField() + the_file = FileField() text = 'Hello, World!' more_text = 'Foo Bar' @@ -1584,14 +1584,14 @@ class FieldTest(unittest.TestCase): SetFile.drop_collection() putfile = PutFile() - putfile.file.put(text, content_type=content_type) + putfile.the_file.put(text, content_type=content_type) putfile.save() putfile.validate() result = PutFile.objects.first() self.assertTrue(putfile == result) - self.assertEquals(result.file.read(), text) - self.assertEquals(result.file.content_type, content_type) - result.file.delete() # Remove file from GridFS + self.assertEquals(result.the_file.read(), text) + self.assertEquals(result.the_file.content_type, content_type) + result.the_file.delete() # Remove file from GridFS PutFile.objects.delete() # Ensure file-like objects are stored @@ -1599,53 +1599,53 @@ class FieldTest(unittest.TestCase): putstring = StringIO.StringIO() putstring.write(text) putstring.seek(0) - putfile.file.put(putstring, content_type=content_type) + putfile.the_file.put(putstring, content_type=content_type) putfile.save() putfile.validate() result = PutFile.objects.first() self.assertTrue(putfile == result) - self.assertEquals(result.file.read(), text) - self.assertEquals(result.file.content_type, content_type) - result.file.delete() + self.assertEquals(result.the_file.read(), text) + self.assertEquals(result.the_file.content_type, content_type) + result.the_file.delete() streamfile = StreamFile() - streamfile.file.new_file(content_type=content_type) - streamfile.file.write(text) - streamfile.file.write(more_text) - streamfile.file.close() + streamfile.the_file.new_file(content_type=content_type) + streamfile.the_file.write(text) + streamfile.the_file.write(more_text) + streamfile.the_file.close() streamfile.save() streamfile.validate() result = StreamFile.objects.first() self.assertTrue(streamfile == result) - self.assertEquals(result.file.read(), text + more_text) - self.assertEquals(result.file.content_type, content_type) - result.file.seek(0) - self.assertEquals(result.file.tell(), 0) - self.assertEquals(result.file.read(len(text)), text) - self.assertEquals(result.file.tell(), len(text)) - self.assertEquals(result.file.read(len(more_text)), more_text) - self.assertEquals(result.file.tell(), len(text + more_text)) - result.file.delete() + self.assertEquals(result.the_file.read(), text + more_text) + self.assertEquals(result.the_file.content_type, content_type) + result.the_file.seek(0) + self.assertEquals(result.the_file.tell(), 0) + self.assertEquals(result.the_file.read(len(text)), text) + self.assertEquals(result.the_file.tell(), len(text)) + self.assertEquals(result.the_file.read(len(more_text)), more_text) + self.assertEquals(result.the_file.tell(), len(text + more_text)) + result.the_file.delete() # Ensure deleted file returns None - self.assertTrue(result.file.read() == None) + self.assertTrue(result.the_file.read() == None) setfile = SetFile() - setfile.file = text + setfile.the_file = text setfile.save() setfile.validate() result = SetFile.objects.first() self.assertTrue(setfile == result) - self.assertEquals(result.file.read(), text) + self.assertEquals(result.the_file.read(), text) # Try replacing file with new one - result.file.replace(more_text) + result.the_file.replace(more_text) result.save() result.validate() result = SetFile.objects.first() self.assertTrue(setfile == result) - self.assertEquals(result.file.read(), more_text) - result.file.delete() + self.assertEquals(result.the_file.read(), more_text) + result.the_file.delete() PutFile.drop_collection() StreamFile.drop_collection() @@ -1653,7 +1653,7 @@ class FieldTest(unittest.TestCase): # Make sure FileField is optional and not required class DemoFile(Document): - file = FileField() + the_file = FileField() DemoFile.objects.create() @@ -1704,20 +1704,20 @@ class FieldTest(unittest.TestCase): """ class TestFile(Document): name = StringField() - file = FileField() + the_file = FileField() # First instance - testfile = TestFile() - testfile.name = "Hello, World!" - testfile.file.put('Hello, World!') - testfile.save() + test_file = TestFile() + test_file.name = "Hello, World!" + test_file.the_file.put('Hello, World!') + test_file.save() # Second instance - testfiledupe = TestFile() - data = testfiledupe.file.read() # Should be None + test_file_dupe = TestFile() + data = test_file_dupe.the_file.read() # Should be None - self.assertTrue(testfile.name != testfiledupe.name) - self.assertTrue(testfile.file.read() != data) + self.assertTrue(test_file.name != test_file_dupe.name) + self.assertTrue(test_file.the_file.read() != data) TestFile.drop_collection() @@ -1725,17 +1725,25 @@ class FieldTest(unittest.TestCase): """Ensure that a boolean test of a FileField indicates its presence """ class TestFile(Document): - file = FileField() + the_file = FileField() - testfile = TestFile() - self.assertFalse(bool(testfile.file)) - testfile.file = 'Hello, World!' - testfile.file.content_type = 'text/plain' - testfile.save() - self.assertTrue(bool(testfile.file)) + test_file = TestFile() + self.assertFalse(bool(test_file.the_file)) + test_file.the_file = 'Hello, World!' + test_file.the_file.content_type = 'text/plain' + test_file.save() + self.assertTrue(bool(test_file.the_file)) TestFile.drop_collection() + def test_file_cmp(self): + """Test comparing against other types""" + class TestFile(Document): + the_file = FileField() + + test_file = TestFile() + self.assertFalse(test_file.the_file in [{"test": 1}]) + def test_image_field(self): class TestImage(Document): @@ -1799,30 +1807,30 @@ class FieldTest(unittest.TestCase): def test_file_multidb(self): - register_connection('testfiles', 'testfiles') + register_connection('test_files', 'test_files') class TestFile(Document): name = StringField() - file = FileField(db_alias="testfiles", - collection_name="macumba") + the_file = FileField(db_alias="test_files", + collection_name="macumba") TestFile.drop_collection() # delete old filesystem - get_db("testfiles").macumba.files.drop() - get_db("testfiles").macumba.chunks.drop() + get_db("test_files").macumba.files.drop() + get_db("test_files").macumba.chunks.drop() # First instance - testfile = TestFile() - testfile.name = "Hello, World!" - testfile.file.put('Hello, World!', + test_file = TestFile() + test_file.name = "Hello, World!" + test_file.the_file.put('Hello, World!', name="hello.txt") - testfile.save() + test_file.save() - data = get_db("testfiles").macumba.files.find_one() + data = get_db("test_files").macumba.files.find_one() self.assertEquals(data.get('name'), 'hello.txt') - testfile = TestFile.objects.first() - self.assertEquals(testfile.file.read(), + test_file = TestFile.objects.first() + self.assertEquals(test_file.the_file.read(), 'Hello, World!') def test_geo_indexes(self): From 0018c38b836af11260c7eee68957459b76cd0a95 Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 1 Aug 2012 13:51:51 +0100 Subject: [PATCH 3/9] Fixed queryset manager issue (MongoEngine/mongoengine#52) --- docs/changelog.rst | 1 + mongoengine/queryset.py | 6 +++--- tests/test_queryset.py | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 2b52582e..f0adcbe5 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,7 @@ Changelog Changes in 0.6.X ================ +- Fixed queryset manager issue (MongoEngine/mongoengine#52) - Fixed FileField comparision (hmarr/mongoengine#547) Changes in 0.6.18 diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index 0d1d95b7..15c768dd 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -1881,10 +1881,10 @@ class QuerySetManager(object): queryset_class = owner._meta['queryset_class'] or QuerySet queryset = queryset_class(owner, owner._get_collection()) if self.get_queryset: - var_names = self.get_queryset.func_code.co_varnames - if len(var_names) == 1: + arg_count = self.get_queryset.func_code.co_argcount + if arg_count == 1: queryset = self.get_queryset(queryset) - elif len(var_names) == 2: + elif arg_count == 2: queryset = self.get_queryset(owner, queryset) else: queryset = partial(self.get_queryset, owner, queryset) diff --git a/tests/test_queryset.py b/tests/test_queryset.py index e623790f..b4ae805b 100644 --- a/tests/test_queryset.py +++ b/tests/test_queryset.py @@ -2287,7 +2287,8 @@ class QuerySetTest(unittest.TestCase): @queryset_manager def objects(cls, qryset): - return qryset(deleted=False) + opts = {"deleted": False} + return qryset(**opts) @queryset_manager def music_posts(doc_cls, queryset, deleted=False): From 2c69d8f0b02ae2b6067611b2fbcb585f4ef6d9ee Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 1 Aug 2012 13:54:24 +0100 Subject: [PATCH 4/9] Updated License --- LICENSE | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LICENSE b/LICENSE index e33b2c59..cef91cca 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2009-2010 Harry Marr - +Copyright (c) 2009-2012 See AUTHORS + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without @@ -8,10 +8,10 @@ copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND From a43d0d46122f42db2ae154b213a27a3cc0bc187f Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 1 Aug 2012 14:57:46 +0100 Subject: [PATCH 5/9] Fixed BinaryField python value issue (MongoEngine/mongoengine#48) --- docs/changelog.rst | 1 + mongoengine/fields.py | 7 ++----- tests/test_fields.py | 17 +++++++++++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index f0adcbe5..58859a58 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,7 @@ Changelog Changes in 0.6.X ================ +- Fixed BinaryField python value issue (MongoEngine/mongoengine#48) - Fixed queryset manager issue (MongoEngine/mongoengine#52) - Fixed FileField comparision (hmarr/mongoengine#547) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index 89b81cdb..27434e67 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -845,12 +845,9 @@ class BinaryField(BaseField): def to_mongo(self, value): return Binary(value) - def to_python(self, value): - return "%s" % value - def validate(self, value): - if not isinstance(value, basestring): - self.error('BinaryField only accepts string values') + if not isinstance(value, (basestring, Binary)): + self.error('BinaryField only accepts string or bson Binary values') if self.max_bytes is not None and len(value) > self.max_bytes: self.error('Binary value is too long') diff --git a/tests/test_fields.py b/tests/test_fields.py index 4e708563..29f5fe97 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -6,6 +6,7 @@ import StringIO import tempfile import gridfs +from bson import Binary from decimal import Decimal from mongoengine import * @@ -1428,7 +1429,7 @@ class FieldTest(unittest.TestCase): attachment_1 = Attachment.objects().first() self.assertEqual(MIME_TYPE, attachment_1.content_type) - self.assertEqual(BLOB, attachment_1.blob) + self.assertEqual(BLOB, str(attachment_1.blob)) Attachment.drop_collection() @@ -1455,7 +1456,7 @@ class FieldTest(unittest.TestCase): attachment_required = AttachmentRequired() self.assertRaises(ValidationError, attachment_required.validate) - attachment_required.blob = '\xe6\x00\xc4\xff\x07' + attachment_required.blob = Binary('\xe6\x00\xc4\xff\x07') attachment_required.validate() attachment_size_limit = AttachmentSizeLimit(blob='\xe6\x00\xc4\xff\x07') @@ -1467,6 +1468,18 @@ class FieldTest(unittest.TestCase): AttachmentRequired.drop_collection() AttachmentSizeLimit.drop_collection() + def test_binary_field_primary(self): + + class Attachment(Document): + id = BinaryField(primary_key=True) + + Attachment.drop_collection() + + att = Attachment(id=uuid.uuid4().bytes).save() + att.delete() + + self.assertEqual(0, Attachment.objects.count()) + def test_choices_validation(self): """Ensure that value is in a container of allowed values. """ From 4226cd08f17061396d5734fb438c7e8856dd491d Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 1 Aug 2012 15:00:14 +0100 Subject: [PATCH 6/9] Updated Changelog --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 58859a58..f5f1dfd9 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,6 +6,7 @@ Changes in 0.6.X ================ - Fixed BinaryField python value issue (MongoEngine/mongoengine#48) +- Fixed SequenceField non numeric value lookup (MongoEngine/mongoengine#41) - Fixed queryset manager issue (MongoEngine/mongoengine#52) - Fixed FileField comparision (hmarr/mongoengine#547) From f23a976bea0a97ecd60f8992ac8bc445c2511194 Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 1 Aug 2012 15:01:21 +0100 Subject: [PATCH 7/9] Added Tommi Komulainen to the contributors list refs MongoEngine/mongoengine#48 --- AUTHORS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index f774d22e..fe8be767 100644 --- a/AUTHORS +++ b/AUTHORS @@ -113,4 +113,5 @@ that much better: * Alexander Koshelev * Jaime Irurzun * Alexandre González - * Thomas Steinacher \ No newline at end of file + * Thomas Steinacher + * Tommi Komulainen \ No newline at end of file From 2420b5e937d29b93ba2a5bc9d464c8367bcdde0c Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 1 Aug 2012 15:14:56 +0100 Subject: [PATCH 8/9] Fixed MapField lookup for fields without declared lookups (MongoEngine/mongoengine#46) --- docs/changelog.rst | 1 + mongoengine/queryset.py | 2 +- tests/test_fields.py | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index f5f1dfd9..1f52dfd4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,7 @@ Changelog Changes in 0.6.X ================ +- Fixed MapField lookup for fields without declared lookups (MongoEngine/mongoengine#46) - Fixed BinaryField python value issue (MongoEngine/mongoengine#48) - Fixed SequenceField non numeric value lookup (MongoEngine/mongoengine#41) - Fixed queryset manager issue (MongoEngine/mongoengine#52) diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index 15c768dd..b7453c6a 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -641,7 +641,7 @@ class QuerySet(object): from mongoengine.fields import ReferenceField, GenericReferenceField if isinstance(field, (ReferenceField, GenericReferenceField)): raise InvalidQueryError('Cannot perform join in mongoDB: %s' % '__'.join(parts)) - if getattr(field, 'field', None): + if hasattr(getattr(field, 'field', None), 'lookup_member'): new_field = field.field.lookup_member(field_name) else: # Look up subfield on the previous field diff --git a/tests/test_fields.py b/tests/test_fields.py index 29f5fe97..d3430031 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -929,6 +929,19 @@ class FieldTest(unittest.TestCase): doc = self.db.test.find_one() self.assertEqual(doc['x']['DICTIONARY_KEY']['i'], 2) + def test_map_field_lookup(self): + """Ensure MapField lookups succeed on Fields without a lookup method""" + + class Log(Document): + name = StringField() + visited = MapField(DateTimeField()) + + Log.drop_collection() + Log(name="wilson", visited={'friends': datetime.now()}).save() + + self.assertEqual(1, Log.objects( + visited__friends__exists=True).count()) + def test_embedded_db_field(self): class Embedded(EmbeddedDocument): From 4b3cea9e78a8bdb68944683f6e94ff3c409fb1ee Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 1 Aug 2012 16:03:33 +0100 Subject: [PATCH 9/9] Added Binary support to UUID (MongoEngine/mongoengine#47) --- docs/changelog.rst | 1 + mongoengine/fields.py | 35 ++++++++++++++++++++----- tests/test_fields.py | 59 ++++++++++++++++++++++++++++++++----------- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 1f52dfd4..08091acb 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,7 @@ Changelog Changes in 0.6.X ================ +- Added Binary support to UUID (MongoEngine/mongoengine#47) - Fixed MapField lookup for fields without declared lookups (MongoEngine/mongoengine#46) - Fixed BinaryField python value issue (MongoEngine/mongoengine#48) - Fixed SequenceField non numeric value lookup (MongoEngine/mongoengine#41) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index 08bbc44c..82689929 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -4,9 +4,9 @@ import decimal import gridfs import re import uuid +import warnings from bson import Binary, DBRef, SON, ObjectId - from base import (BaseField, ComplexBaseField, ObjectIdField, ValidationError, get_document, BaseDocument) from queryset import DO_NOTHING, QuerySet @@ -1308,17 +1308,40 @@ class UUIDField(BaseField): .. versionadded:: 0.6 """ + _binary = None - def __init__(self, **kwargs): + def __init__(self, binary=None, **kwargs): + """ + Store UUID data in the database + + :param binary: (optional) boolean store as binary. + + .. versionchanged:: 0.6.19 + """ + if binary is None: + binary = False + msg = ("UUIDFields will soon default to store as binary, please " + "configure binary=False if you wish to store as a string") + warnings.warn(msg, FutureWarning) + self._binary = binary super(UUIDField, self).__init__(**kwargs) def to_python(self, value): - if not isinstance(value, basestring): - value = unicode(value) - return uuid.UUID(value) + if not self.binary: + if not isinstance(value, basestring): + value = unicode(value) + return uuid.UUID(value) + return value def to_mongo(self, value): - return unicode(value) + if not self._binary: + return unicode(value) + return value + + def prepare_query_value(self, op, value): + if value is None: + return None + return self.to_mongo(value) def validate(self, value): if not isinstance(value, uuid.UUID): diff --git a/tests/test_fields.py b/tests/test_fields.py index d3430031..c4013c10 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -272,25 +272,54 @@ class FieldTest(unittest.TestCase): person.admin = 'Yes' self.assertRaises(ValidationError, person.validate) - def test_uuid_validation(self): - """Ensure that invalid values cannot be assigned to UUID fields. + def test_uuid_field_string(self): + """Test UUID fields storing as String """ class Person(Document): - api_key = UUIDField() + api_key = UUIDField(binary=False) + + Person.drop_collection() + + uu = uuid.uuid4() + Person(api_key=uu).save() + self.assertEqual(1, Person.objects(api_key=uu).count()) person = Person() - # any uuid type is valid - person.api_key = uuid.uuid4() - person.validate() - person.api_key = uuid.uuid1() - person.validate() + valid = (uuid.uuid4(), uuid.uuid1()) + for api_key in valid: + person.api_key = api_key + person.validate() + + invalid = ('9d159858-549b-4975-9f98-dd2f987c113g', + '9d159858-549b-4975-9f98-dd2f987c113') + for api_key in invalid: + person.api_key = api_key + self.assertRaises(ValidationError, person.validate) + + def test_uuid_field_binary(self): + """Test UUID fields storing as Binary object + """ + class Person(Document): + api_key = UUIDField(binary=True) + + Person.drop_collection() + + uu = uuid.uuid4() + Person(api_key=uu).save() + self.assertEqual(1, Person.objects(api_key=uu).count()) + + person = Person() + valid = (uuid.uuid4(), uuid.uuid1()) + for api_key in valid: + person.api_key = api_key + person.validate() + + invalid = ('9d159858-549b-4975-9f98-dd2f987c113g', + '9d159858-549b-4975-9f98-dd2f987c113') + for api_key in invalid: + person.api_key = api_key + self.assertRaises(ValidationError, person.validate) - # last g cannot belong to an hex number - person.api_key = '9d159858-549b-4975-9f98-dd2f987c113g' - self.assertRaises(ValidationError, person.validate) - # short strings don't validate - person.api_key = '9d159858-549b-4975-9f98-dd2f987c113' - self.assertRaises(ValidationError, person.validate) def test_datetime_validation(self): """Ensure that invalid values cannot be assigned to datetime fields. @@ -937,7 +966,7 @@ class FieldTest(unittest.TestCase): visited = MapField(DateTimeField()) Log.drop_collection() - Log(name="wilson", visited={'friends': datetime.now()}).save() + Log(name="wilson", visited={'friends': datetime.datetime.now()}).save() self.assertEqual(1, Log.objects( visited__friends__exists=True).count())