From bdbd495a9e778d12157b789a74e0e00a303b5efd Mon Sep 17 00:00:00 2001 From: DavidBord Date: Sun, 17 Aug 2014 13:57:48 +0300 Subject: [PATCH] fix-#734: set attribute to None does not work (at least for fields with default values). Solves #735 as well --- docs/changelog.rst | 1 + mongoengine/base/fields.py | 16 +++++++++++----- tests/document/instance.py | 21 +++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 1feec3439..1842dca80 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,7 @@ Changelog Changes in 0.9.X - DEV ====================== +- Set attribute to None does not work (at least for fields with default values) #734 - Querying by a field defined in a subclass raises InvalidQueryError #744 - Add Support For MongoDB 2.6.X's maxTimeMS #778 - abstract shouldn't be inherited in EmbeddedDocument # 789 diff --git a/mongoengine/base/fields.py b/mongoengine/base/fields.py index 5bb9c7ac4..2747dde1d 100644 --- a/mongoengine/base/fields.py +++ b/mongoengine/base/fields.py @@ -37,7 +37,7 @@ class BaseField(object): def __init__(self, db_field=None, name=None, required=False, default=None, unique=False, unique_with=None, primary_key=False, validation=None, choices=None, verbose_name=None, - help_text=None): + help_text=None, null=False): """ :param db_field: The database field to store this field in (defaults to the name of the field) @@ -60,6 +60,8 @@ def __init__(self, db_field=None, name=None, required=False, default=None, model forms from the document model. :param help_text: (optional) The help text for this field and is often used when generating model forms from the document model. + :param null: (optional) Is the field value can be null. If no and there is a default value + then the default value is set """ self.db_field = (db_field or name) if not primary_key else '_id' @@ -75,6 +77,7 @@ def __init__(self, db_field=None, name=None, required=False, default=None, self.choices = choices self.verbose_name = verbose_name self.help_text = help_text + self.null = null # Adjust the appropriate creation counter, and save our local copy. if self.db_field == '_id': @@ -100,10 +103,13 @@ def __set__(self, instance, value): # If setting to None and theres a default # Then set the value to the default value - if value is None and self.default is not None: - value = self.default - if callable(value): - value = value() + if value is None: + if self.null: + value = None + elif self.default is not None: + value = self.default + if callable(value): + value = value() if instance._initialised: try: diff --git a/tests/document/instance.py b/tests/document/instance.py index 360d53851..6bb203002 100644 --- a/tests/document/instance.py +++ b/tests/document/instance.py @@ -2706,5 +2706,26 @@ class Person(Document): self.assertEquals(p4.height, 189) self.assertEquals(Person.objects(height=189).count(), 1) + def test_null_field(self): + # 734 + class User(Document): + name = StringField() + height = IntField(default=184, null=True) + User.objects.delete() + u = User(name='user') + u.save() + u_from_db = User.objects.get(name='user') + u_from_db.height = None + u_from_db.save() + self.assertEquals(u_from_db.height, None) + + # 735 + User.objects.delete() + u = User(name='user') + u.save() + User.objects(name='user').update_one(set__height=None, upsert=True) + u_from_db = User.objects.get(name='user') + self.assertEquals(u_from_db.height, None) + if __name__ == '__main__': unittest.main()