added GenericEmbeddedDocumentField
This commit is contained in:
		| @@ -21,7 +21,7 @@ __all__ = ['StringField', 'IntField', 'FloatField', 'BooleanField', | |||||||
|            'DecimalField', 'ComplexDateTimeField', 'URLField', |            'DecimalField', 'ComplexDateTimeField', 'URLField', | ||||||
|            'GenericReferenceField', 'FileField', 'BinaryField', |            'GenericReferenceField', 'FileField', 'BinaryField', | ||||||
|            'SortedListField', 'EmailField', 'GeoPointField', |            'SortedListField', 'EmailField', 'GeoPointField', | ||||||
|            'SequenceField'] |            'SequenceField', 'GenericEmbeddedDocumentField'] | ||||||
|  |  | ||||||
| RECURSIVE_REFERENCE_CONSTANT = 'self' | RECURSIVE_REFERENCE_CONSTANT = 'self' | ||||||
|  |  | ||||||
| @@ -420,6 +420,32 @@ class EmbeddedDocumentField(BaseField): | |||||||
|     def prepare_query_value(self, op, value): |     def prepare_query_value(self, op, value): | ||||||
|         return self.to_mongo(value) |         return self.to_mongo(value) | ||||||
|  |  | ||||||
|  | class GenericEmbeddedDocumentField(BaseField): | ||||||
|  |     def prepare_query_value(self, op, value): | ||||||
|  |         return self.to_mongo(value) | ||||||
|  |  | ||||||
|  |     def to_python(self, value): | ||||||
|  |         if isinstance(value, dict): | ||||||
|  |             doc_cls = get_document(value['_cls']) | ||||||
|  |             value = doc_cls._from_son(value) | ||||||
|  |  | ||||||
|  |         return value | ||||||
|  |  | ||||||
|  |     def validate(self, value): | ||||||
|  |         if not isinstance(value, EmbeddedDocument): | ||||||
|  |             raise ValidationError('Invalid embedded document instance ' | ||||||
|  |                                   'provided to an GenericEmbeddedDocumentField') | ||||||
|  |  | ||||||
|  |         value.validate() | ||||||
|  |  | ||||||
|  |     def to_mongo(self, document): | ||||||
|  |         if document is None: | ||||||
|  |             return None | ||||||
|  |  | ||||||
|  |         data = document.to_mongo() | ||||||
|  |         if not '_cls' in data: | ||||||
|  |             data['_cls'] = document._class_name | ||||||
|  |         return data | ||||||
|  |  | ||||||
| class ListField(ComplexBaseField): | class ListField(ComplexBaseField): | ||||||
|     """A list field that wraps a standard field, allowing multiple instances |     """A list field that wraps a standard field, allowing multiple instances | ||||||
|   | |||||||
| @@ -1488,5 +1488,30 @@ class FieldTest(unittest.TestCase): | |||||||
|         self.assertEqual(c['next'], 10) |         self.assertEqual(c['next'], 10) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def test_generic_embedded_document(self): | ||||||
|  |         class Car(EmbeddedDocument): | ||||||
|  |             name = StringField() | ||||||
|  |  | ||||||
|  |         class Dish(EmbeddedDocument): | ||||||
|  |             food = StringField(required=True) | ||||||
|  |             number = IntField() | ||||||
|  |  | ||||||
|  |         class Person(Document): | ||||||
|  |             name = StringField() | ||||||
|  |             like = GenericEmbeddedDocumentField() | ||||||
|  |  | ||||||
|  |         person = Person(name='Test User') | ||||||
|  |         person.like = Car(name='Fiat') | ||||||
|  |         person.save() | ||||||
|  |  | ||||||
|  |         person = Person.objects.first() | ||||||
|  |         self.assertTrue(isinstance(person.like, Car)) | ||||||
|  |  | ||||||
|  |         person.like = Dish(food="arroz", number=15) | ||||||
|  |         person.save() | ||||||
|  |  | ||||||
|  |         person = Person.objects.first() | ||||||
|  |         self.assertTrue(isinstance(person.like, Dish)) | ||||||
|  |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     unittest.main() |     unittest.main() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user