diff --git a/.gitignore b/.gitignore index 51a9ca1d..d67429a2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,7 @@ docs/_build build/ dist/ mongoengine.egg-info/ -env/ \ No newline at end of file +env/ +.settings +.project +.pydevproject \ No newline at end of file diff --git a/mongoengine/base.py b/mongoengine/base.py index 6b74cb07..589042e2 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -25,6 +25,12 @@ class BaseField(object): _index_with_types = True _geo_index = False + # These track each time a Field instance is created. Used to retain order. + # The auto_creation_counter is used for fields that MongoEngine implicitly + # creates, creation_counter is used for all user-specified fields. + creation_counter = 0 + auto_creation_counter = -1 + def __init__(self, db_field=None, name=None, required=False, default=None, unique=False, unique_with=None, primary_key=False, validation=None, choices=None): @@ -41,6 +47,13 @@ class BaseField(object): self.primary_key = primary_key self.validation = validation self.choices = choices + # Adjust the appropriate creation counter, and save our local copy. + if self.db_field == '_id': + self.creation_counter = BaseField.auto_creation_counter + BaseField.auto_creation_counter -= 1 + else: + self.creation_counter = BaseField.creation_counter + BaseField.creation_counter += 1 def __get__(self, instance, owner): """Descriptor for retrieving a value from a field in a document. Do @@ -87,9 +100,9 @@ class BaseField(object): def _validate(self, value): # check choices if self.choices is not None: - if value not in self.choices: - raise ValidationError("Value must be one of %s." - % unicode(self.choices)) + option_keys = [option_key for option_key, option_value in self.choices] + if value not in option_keys: + raise ValidationError("Value must be one of %s." % unicode(option_keys)) # check validation argument if self.validation is not None: @@ -241,8 +254,8 @@ class TopLevelDocumentMetaclass(DocumentMetaclass): # Propagate index options. for key in ('index_background', 'index_drop_dups', 'index_opts'): - if key in base._meta: - base_meta[key] = base._meta[key] + if key in base._meta: + base_meta[key] = base._meta[key] id_field = id_field or base._meta.get('id_field') base_indexes += base._meta.get('indexes', []) @@ -491,6 +504,7 @@ class BaseDocument(object): if sys.version_info < (2, 5): # Prior to Python 2.5, Exception was an old-style class + import types def subclass_exception(name, parents, unused): return types.ClassType(name, parents, {}) else: diff --git a/mongoengine/fields.py b/mongoengine/fields.py index e95fd65e..e95312f9 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -12,7 +12,6 @@ import datetime import decimal import gridfs import warnings -import types __all__ = ['StringField', 'IntField', 'FloatField', 'BooleanField', diff --git a/tests/fields.py b/tests/fields.py index 5602cdec..034ec61e 100644 --- a/tests/fields.py +++ b/tests/fields.py @@ -644,7 +644,8 @@ class FieldTest(unittest.TestCase): """Ensure that value is in a container of allowed values. """ class Shirt(Document): - size = StringField(max_length=3, choices=('S','M','L','XL','XXL')) + size = StringField(max_length=3, choices=(('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), + ('XL', 'Extra Large'), ('XXL', 'Extra Extra Large'))) Shirt.drop_collection()