From e6a30f899c9bb6cdb28e2302967e6dc96ceac055 Mon Sep 17 00:00:00 2001 From: "Bo.Yi" Date: Thu, 6 Jul 2017 14:57:03 +0800 Subject: [PATCH 1/3] [fix]validation list field with multi choice values --- mongoengine/base/document.py | 6 +++++- mongoengine/base/fields.py | 6 ++++-- tests/fields/fields.py | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py index 99c8af87..43158133 100644 --- a/mongoengine/base/document.py +++ b/mongoengine/base/document.py @@ -1080,5 +1080,9 @@ class BaseDocument(object): """Return the display value for a choice field""" value = getattr(self, field.name) if field.choices and isinstance(field.choices[0], (list, tuple)): - return dict(field.choices).get(value, value) + sep = getattr(field, 'display_sep', u' ') + values = value if field.__name__ == 'ListField' else [value] + return sep.join([ + dict(field.choices).get(val, val) + for val in values]) return value diff --git a/mongoengine/base/fields.py b/mongoengine/base/fields.py index e2b5d321..69034d5d 100644 --- a/mongoengine/base/fields.py +++ b/mongoengine/base/fields.py @@ -213,8 +213,10 @@ class BaseField(object): ) ) # Choices which are types other than Documents - elif value not in choice_list: - self.error('Value must be one of %s' % six.text_type(choice_list)) + else: + values = value if isinstance(value, (list, tuple)) else [value] + if len(set(values) - set(choice_list)): + self.error('Value must be one of %s' % six.text_type(choice_list)) def _validate(self, value, **kwargs): # Check the Choices Constraint diff --git a/tests/fields/fields.py b/tests/fields/fields.py index 7a0ccc25..b6628ab0 100644 --- a/tests/fields/fields.py +++ b/tests/fields/fields.py @@ -920,6 +920,12 @@ class FieldTest(MongoDBTestCase): def test_list_validation(self): """Ensure that a list field only accepts lists with valid elements.""" + AccessLevelChoices = ( + ('a', u'Administrator'), + ('b', u'Manager'), + ('c', u'Staff'), + ) + class User(Document): pass @@ -932,6 +938,7 @@ class FieldTest(MongoDBTestCase): tags = ListField(StringField()) authors = ListField(ReferenceField(User)) generic = ListField(GenericReferenceField()) + access_list = ListField(required=False, default=[], choices=AccessLevelChoices, display_sep=u',') User.drop_collection() BlogPost.drop_collection() @@ -949,6 +956,17 @@ class FieldTest(MongoDBTestCase): post.tags = ('fun', 'leisure') post.validate() + post.access_list = 'a,b' + self.assertRaises(ValidationError, post.validate()) + + post.access_list = ['c', 'd'] + self.assertRaises(ValidationError, post.validate()) + + post.access_list = ['a', 'b'] + post.validate() + + self.assertEqual(post.get_access_list_display(), u'Administrator,Manager') + post.comments = ['a'] self.assertRaises(ValidationError, post.validate) post.comments = 'yay' From 820b5cbb86a0cc9dff65db35b0f806fb811a512b Mon Sep 17 00:00:00 2001 From: "Bo.Yi" Date: Thu, 6 Jul 2017 16:07:51 +0800 Subject: [PATCH 2/3] [fix]pass test case and fix field type error --- mongoengine/base/document.py | 6 ++++-- tests/fields/fields.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py index 43158133..42a8bb4b 100644 --- a/mongoengine/base/document.py +++ b/mongoengine/base/document.py @@ -1080,9 +1080,11 @@ class BaseDocument(object): """Return the display value for a choice field""" value = getattr(self, field.name) if field.choices and isinstance(field.choices[0], (list, tuple)): + if value is None: + return None sep = getattr(field, 'display_sep', u' ') - values = value if field.__name__ == 'ListField' else [value] + values = value if field.__class__.__name__ == 'ListField' else [value] return sep.join([ dict(field.choices).get(val, val) - for val in values]) + for val in values or []]) return value diff --git a/tests/fields/fields.py b/tests/fields/fields.py index b6628ab0..336e116c 100644 --- a/tests/fields/fields.py +++ b/tests/fields/fields.py @@ -957,10 +957,10 @@ class FieldTest(MongoDBTestCase): post.validate() post.access_list = 'a,b' - self.assertRaises(ValidationError, post.validate()) + self.assertRaises(ValidationError, post.validate) post.access_list = ['c', 'd'] - self.assertRaises(ValidationError, post.validate()) + self.assertRaises(ValidationError, post.validate) post.access_list = ['a', 'b'] post.validate() From 9f02f71c52f5f9c02cbd3db797ae80aea36d0639 Mon Sep 17 00:00:00 2001 From: "Bo.Yi" Date: Sun, 16 Jul 2017 18:47:20 +0800 Subject: [PATCH 3/3] [fix]fix some personal hobby --- mongoengine/base/document.py | 4 ++-- tests/fields/fields.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py index 42a8bb4b..bb8d3a16 100644 --- a/mongoengine/base/document.py +++ b/mongoengine/base/document.py @@ -1082,8 +1082,8 @@ class BaseDocument(object): if field.choices and isinstance(field.choices[0], (list, tuple)): if value is None: return None - sep = getattr(field, 'display_sep', u' ') - values = value if field.__class__.__name__ == 'ListField' else [value] + sep = getattr(field, 'display_sep', ' ') + values = value if field.__class__.__name__ in ('ListField', 'SortedListField') else [value] return sep.join([ dict(field.choices).get(val, val) for val in values or []]) diff --git a/tests/fields/fields.py b/tests/fields/fields.py index 336e116c..1dc25d12 100644 --- a/tests/fields/fields.py +++ b/tests/fields/fields.py @@ -921,7 +921,7 @@ class FieldTest(MongoDBTestCase): def test_list_validation(self): """Ensure that a list field only accepts lists with valid elements.""" AccessLevelChoices = ( - ('a', u'Administrator'), + ('a', u'Administration'), ('b', u'Manager'), ('c', u'Staff'), ) @@ -938,7 +938,7 @@ class FieldTest(MongoDBTestCase): tags = ListField(StringField()) authors = ListField(ReferenceField(User)) generic = ListField(GenericReferenceField()) - access_list = ListField(required=False, default=[], choices=AccessLevelChoices, display_sep=u',') + access_list = ListField(choices=AccessLevelChoices, display_sep=', ') User.drop_collection() BlogPost.drop_collection() @@ -965,7 +965,7 @@ class FieldTest(MongoDBTestCase): post.access_list = ['a', 'b'] post.validate() - self.assertEqual(post.get_access_list_display(), u'Administrator,Manager') + self.assertEqual(post.get_access_list_display(), u'Administration, Manager') post.comments = ['a'] self.assertRaises(ValidationError, post.validate)