Implemented Choices for GenericReferenceFields
Refs mongoengine/mongoengine#13
This commit is contained in:
		| @@ -4,7 +4,8 @@ Changelog | |||||||
|  |  | ||||||
| Changes in 0.6.X | Changes in 0.6.X | ||||||
| ================ | ================ | ||||||
| - Added choices for GenericEmbeddedDocuments | - Added support for choices with GenericReferenceFields | ||||||
|  | - Added support for choices with GenericEmbeddedDocumentFields | ||||||
| - Fixed Django 1.4 sessions first save data loss | - Fixed Django 1.4 sessions first save data loss | ||||||
| - FileField now automatically delete files on .delete() | - FileField now automatically delete files on .delete() | ||||||
| - Fix for GenericReference to_mongo method | - Fix for GenericReference to_mongo method | ||||||
|   | |||||||
| @@ -223,11 +223,10 @@ class BaseField(object): | |||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     def _validate(self, value): |     def _validate(self, value): | ||||||
|         from mongoengine import EmbeddedDocument |         from mongoengine import Document, EmbeddedDocument | ||||||
|  |  | ||||||
|         # check choices |         # check choices | ||||||
|         if self.choices: |         if self.choices: | ||||||
|             is_cls = isinstance(value, EmbeddedDocument) |             is_cls = isinstance(value, (Document, EmbeddedDocument)) | ||||||
|             value_to_check = value.__class__ if is_cls else value |             value_to_check = value.__class__ if is_cls else value | ||||||
|             err_msg = 'an instance' if is_cls else 'one' |             err_msg = 'an instance' if is_cls else 'one' | ||||||
|             if isinstance(self.choices[0], (list, tuple)): |             if isinstance(self.choices[0], (list, tuple)): | ||||||
|   | |||||||
| @@ -441,6 +441,9 @@ class GenericEmbeddedDocumentField(BaseField): | |||||||
|     :class:`~mongoengine.EmbeddedDocument` to be stored. |     :class:`~mongoengine.EmbeddedDocument` to be stored. | ||||||
|  |  | ||||||
|     Only valid values are subclasses of :class:`~mongoengine.EmbeddedDocument`. |     Only valid values are subclasses of :class:`~mongoengine.EmbeddedDocument`. | ||||||
|  |  | ||||||
|  |     ..note :: You can use the choices param to limit the acceptable | ||||||
|  |     EmbeddedDocument types | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     def prepare_query_value(self, op, value): |     def prepare_query_value(self, op, value): | ||||||
| @@ -701,6 +704,8 @@ class GenericReferenceField(BaseField): | |||||||
|     ..note ::  Any documents used as a generic reference must be registered in the |     ..note ::  Any documents used as a generic reference must be registered in the | ||||||
|     document registry.  Importing the model will automatically register it. |     document registry.  Importing the model will automatically register it. | ||||||
|  |  | ||||||
|  |     ..note :: You can use the choices param to limit the acceptable Document types | ||||||
|  |  | ||||||
|     .. versionadded:: 0.3 |     .. versionadded:: 0.3 | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1301,6 +1301,74 @@ class FieldTest(unittest.TestCase): | |||||||
|         self.assertEquals(repr(Person.objects(city=None)), |         self.assertEquals(repr(Person.objects(city=None)), | ||||||
|                             "[<Person: Person object>]") |                             "[<Person: Person object>]") | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def test_generic_reference_choices(self): | ||||||
|  |         """Ensure that a GenericReferenceField can handle choices | ||||||
|  |         """ | ||||||
|  |         class Link(Document): | ||||||
|  |             title = StringField() | ||||||
|  |  | ||||||
|  |         class Post(Document): | ||||||
|  |             title = StringField() | ||||||
|  |  | ||||||
|  |         class Bookmark(Document): | ||||||
|  |             bookmark_object = GenericReferenceField(choices=(Post,)) | ||||||
|  |  | ||||||
|  |         Link.drop_collection() | ||||||
|  |         Post.drop_collection() | ||||||
|  |         Bookmark.drop_collection() | ||||||
|  |  | ||||||
|  |         link_1 = Link(title="Pitchfork") | ||||||
|  |         link_1.save() | ||||||
|  |  | ||||||
|  |         post_1 = Post(title="Behind the Scenes of the Pavement Reunion") | ||||||
|  |         post_1.save() | ||||||
|  |  | ||||||
|  |         bm = Bookmark(bookmark_object=link_1) | ||||||
|  |         self.assertRaises(ValidationError, bm.validate) | ||||||
|  |  | ||||||
|  |         bm = Bookmark(bookmark_object=post_1) | ||||||
|  |         bm.save() | ||||||
|  |  | ||||||
|  |         bm = Bookmark.objects.first() | ||||||
|  |         self.assertEqual(bm.bookmark_object, post_1) | ||||||
|  |  | ||||||
|  |     def test_generic_reference_list_choices(self): | ||||||
|  |         """Ensure that a ListField properly dereferences generic references and | ||||||
|  |         respects choices. | ||||||
|  |         """ | ||||||
|  |         class Link(Document): | ||||||
|  |             title = StringField() | ||||||
|  |  | ||||||
|  |         class Post(Document): | ||||||
|  |             title = StringField() | ||||||
|  |  | ||||||
|  |         class User(Document): | ||||||
|  |             bookmarks = ListField(GenericReferenceField(choices=(Post,))) | ||||||
|  |  | ||||||
|  |         Link.drop_collection() | ||||||
|  |         Post.drop_collection() | ||||||
|  |         User.drop_collection() | ||||||
|  |  | ||||||
|  |         link_1 = Link(title="Pitchfork") | ||||||
|  |         link_1.save() | ||||||
|  |  | ||||||
|  |         post_1 = Post(title="Behind the Scenes of the Pavement Reunion") | ||||||
|  |         post_1.save() | ||||||
|  |  | ||||||
|  |         user = User(bookmarks=[link_1]) | ||||||
|  |         self.assertRaises(ValidationError, user.validate) | ||||||
|  |  | ||||||
|  |         user = User(bookmarks=[post_1]) | ||||||
|  |         user.save() | ||||||
|  |  | ||||||
|  |         user = User.objects.first() | ||||||
|  |         self.assertEqual(user.bookmarks, [post_1]) | ||||||
|  |  | ||||||
|  |         Link.drop_collection() | ||||||
|  |         Post.drop_collection() | ||||||
|  |         User.drop_collection() | ||||||
|  |  | ||||||
|     def test_binary_fields(self): |     def test_binary_fields(self): | ||||||
|         """Ensure that binary fields can be stored and retrieved. |         """Ensure that binary fields can be stored and retrieved. | ||||||
|         """ |         """ | ||||||
| @@ -1893,6 +1961,8 @@ class FieldTest(unittest.TestCase): | |||||||
|         self.assertTrue(isinstance(person.like, Dish)) |         self.assertTrue(isinstance(person.like, Dish)) | ||||||
|  |  | ||||||
|     def test_generic_embedded_document_choices(self): |     def test_generic_embedded_document_choices(self): | ||||||
|  |         """Ensure you can limit GenericEmbeddedDocument choices | ||||||
|  |         """ | ||||||
|         class Car(EmbeddedDocument): |         class Car(EmbeddedDocument): | ||||||
|             name = StringField() |             name = StringField() | ||||||
|  |  | ||||||
| @@ -1917,6 +1987,9 @@ class FieldTest(unittest.TestCase): | |||||||
|         self.assertTrue(isinstance(person.like, Dish)) |         self.assertTrue(isinstance(person.like, Dish)) | ||||||
|  |  | ||||||
|     def test_generic_list_embedded_document_choices(self): |     def test_generic_list_embedded_document_choices(self): | ||||||
|  |         """Ensure you can limit GenericEmbeddedDocument choices inside a list | ||||||
|  |         field | ||||||
|  |         """ | ||||||
|         class Car(EmbeddedDocument): |         class Car(EmbeddedDocument): | ||||||
|             name = StringField() |             name = StringField() | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user