diff --git a/mongoengine/base.py b/mongoengine/base.py index a95339eb..8028ca97 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -468,8 +468,23 @@ class ObjectIdField(BaseField): class DocumentMetaclass(type): """Metaclass for all documents. """ - + + def __new__(cls, name, bases, attrs): + def _get_mixin_fields(base): + attrs = {} + attrs.update(dict([(k, v) for k, v in base.__dict__.items() + if issubclass(v.__class__, BaseField)])) + + for p_base in base.__bases__: + #optimize :-) + if p_base in (object, BaseDocument): + continue + + attrs.update(_get_mixin_fields(p_base)) + + return attrs + metaclass = attrs.get('__metaclass__') super_new = super(DocumentMetaclass, cls).__new__ if metaclass and issubclass(metaclass, DocumentMetaclass): @@ -488,8 +503,7 @@ class DocumentMetaclass(type): superclasses[base._class_name] = base superclasses.update(base._superclasses) else: # Add any mixin fields - attrs.update(dict([(k, v) for k, v in base.__dict__.items() - if issubclass(v.__class__, BaseField)])) + attrs.update(_get_mixin_fields(base)) if hasattr(base, '_meta') and not base._meta.get('abstract'): # Ensure that the Document class may be subclassed - diff --git a/tests/document.py b/tests/document.py index 021addce..dabc27e1 100644 --- a/tests/document.py +++ b/tests/document.py @@ -2175,6 +2175,30 @@ class DocumentTest(unittest.TestCase): Person.drop_collection() + def test_mixin_inheritance(self): + class BaseMixIn(object): + count = IntField() + data = StringField() + + class DoubleMixIn(BaseMixIn): + comment = StringField() + + class TestDoc(Document, DoubleMixIn): + age = IntField() + + TestDoc.drop_collection() + t = TestDoc(count=12, data="test", + comment="great!", age=19) + + t.save() + + t = TestDoc.objects.first() + + self.assertEquals(t.age, 19) + self.assertEquals(t.comment, "great!") + self.assertEquals(t.data, "test") + self.assertEquals(t.count, 12) + def test_save_reference(self): """Ensure that a document reference field may be saved in the database. """