Merge branch 'master' of github.com:MongoEngine/mongoengine into release_0_19_0
This commit is contained in:
		| @@ -744,7 +744,7 @@ Document inheritance | ||||
|  | ||||
| To create a specialised type of a :class:`~mongoengine.Document` you have | ||||
| defined, you may subclass it and add any extra fields or methods you may need. | ||||
| As this is new class is not a direct subclass of | ||||
| As this new class is not a direct subclass of | ||||
| :class:`~mongoengine.Document`, it will not be stored in its own collection; it | ||||
| will use the same collection as its superclass uses. This allows for more | ||||
| convenient and efficient retrieval of related documents -- all you need do is | ||||
| @@ -767,6 +767,27 @@ document.:: | ||||
|           Setting :attr:`allow_inheritance` to True should also be used in | ||||
|           :class:`~mongoengine.EmbeddedDocument` class in case you need to subclass it | ||||
|  | ||||
| When it comes to querying using :attr:`.objects()`, querying `Page.objects()` will query | ||||
| both `Page` and `DatedPage` whereas querying `DatedPage` will only query the `DatedPage` documents. | ||||
| Behind the scenes, MongoEngine deals with inheritance by adding a :attr:`_cls` attribute that contains | ||||
| the class name in every documents. When a document is loaded, MongoEngine checks | ||||
| it's :attr:`_cls` attribute and use that class to construct the instance.:: | ||||
|  | ||||
|     Page(title='a funky title').save() | ||||
|     DatedPage(title='another title', date=datetime.utcnow()).save() | ||||
|  | ||||
|     print(Page.objects().count())         # 2 | ||||
|     print(DatedPage.objects().count())    # 1 | ||||
|  | ||||
|     # print documents in their native form | ||||
|     # we remove 'id' to avoid polluting the output with unnecessary detail | ||||
|     qs = Page.objects.exclude('id').as_pymongo() | ||||
|     print(list(qs)) | ||||
|     # [ | ||||
|     #   {'_cls': u 'Page', 'title': 'a funky title'}, | ||||
|     #   {'_cls': u 'Page.DatedPage', 'title': u 'another title', 'date': datetime.datetime(2019, 12, 13, 20, 16, 59, 993000)} | ||||
|     # ] | ||||
|  | ||||
| Working with existing data | ||||
| -------------------------- | ||||
| As MongoEngine no longer defaults to needing :attr:`_cls`, you can quickly and | ||||
|   | ||||
| @@ -2,10 +2,10 @@ | ||||
| Use mongomock for testing | ||||
| ============================== | ||||
|  | ||||
| `mongomock <https://github.com/vmalloc/mongomock/>`_ is a package to do just  | ||||
| `mongomock <https://github.com/vmalloc/mongomock/>`_ is a package to do just | ||||
| what the name implies, mocking a mongo database. | ||||
|  | ||||
| To use with mongoengine, simply specify mongomock when connecting with  | ||||
| To use with mongoengine, simply specify mongomock when connecting with | ||||
| mongoengine: | ||||
|  | ||||
| .. code-block:: python | ||||
| @@ -21,7 +21,7 @@ or with an alias: | ||||
|     conn = get_connection('testdb') | ||||
|  | ||||
| Example of test file: | ||||
| -------- | ||||
| --------------------- | ||||
| .. code-block:: python | ||||
|  | ||||
|     import unittest | ||||
| @@ -45,4 +45,4 @@ Example of test file: | ||||
|             pers.save() | ||||
|  | ||||
|             fresh_pers = Person.objects().first() | ||||
|             self.assertEqual(fresh_pers.name, 'John') | ||||
|             assert fresh_pers.name ==  'John' | ||||
|   | ||||
| @@ -222,6 +222,18 @@ keyword argument:: | ||||
|  | ||||
| .. versionadded:: 0.4 | ||||
|  | ||||
| Sorting/Ordering results | ||||
| ======================== | ||||
| It is possible to order the results by 1 or more keys using :meth:`~mongoengine.queryset.QuerySet.order_by`. | ||||
| The order may be specified by prepending each of the keys by "+" or "-". Ascending order is assumed if there's no prefix.:: | ||||
|  | ||||
|     # Order by ascending date | ||||
|     blogs = BlogPost.objects().order_by('date')    # equivalent to .order_by('+date') | ||||
|  | ||||
|     # Order by ascending date first, then descending title | ||||
|     blogs = BlogPost.objects().order_by('+date', '-title') | ||||
|  | ||||
|  | ||||
| Limiting and skipping results | ||||
| ============================= | ||||
| Just as with traditional ORMs, you may limit the number of results returned or | ||||
| @@ -585,7 +597,8 @@ cannot use the `$` syntax in keyword arguments it has been mapped to `S`:: | ||||
|     ['database', 'mongodb'] | ||||
|  | ||||
| From MongoDB version 2.6, push operator supports $position value which allows | ||||
| to push values with index. | ||||
| to push values with index:: | ||||
|  | ||||
|     >>> post = BlogPost(title="Test", tags=["mongo"]) | ||||
|     >>> post.save() | ||||
|     >>> post.update(push__tags__0=["database", "code"]) | ||||
|   | ||||
| @@ -120,6 +120,9 @@ class BaseList(list): | ||||
|         super(BaseList, self).__init__(list_items) | ||||
|  | ||||
|     def __getitem__(self, key): | ||||
|         # change index to positive value because MongoDB does not support negative one | ||||
|         if isinstance(key, int) and key < 0: | ||||
|             key = len(self) + key | ||||
|         value = super(BaseList, self).__getitem__(key) | ||||
|  | ||||
|         if isinstance(key, slice): | ||||
|   | ||||
| @@ -41,7 +41,7 @@ from tests.utils import MongoDBTestCase, get_as_pymongo | ||||
| TEST_IMAGE_PATH = os.path.join(os.path.dirname(__file__), "../fields/mongoengine.png") | ||||
|  | ||||
|  | ||||
| class TestInstance(MongoDBTestCase): | ||||
| class TestDocumentInstance(MongoDBTestCase): | ||||
|     def setUp(self): | ||||
|         class Job(EmbeddedDocument): | ||||
|             name = StringField() | ||||
| @@ -3338,19 +3338,19 @@ class TestInstance(MongoDBTestCase): | ||||
|  | ||||
|         # worker1.job should be equal to the job used originally to create the | ||||
|         # document. | ||||
|         self.assertEqual(worker1.job, worker.job) | ||||
|         assert worker1.job == worker.job | ||||
|  | ||||
|         # worker1.job should be equal to a newly created Job EmbeddedDocument | ||||
|         # using either the Boss object or his ID. | ||||
|         self.assertEqual(worker1.job, Job(boss=boss, boss_dbref=boss)) | ||||
|         self.assertEqual(worker1.job, Job(boss=boss.id, boss_dbref=boss.id)) | ||||
|         assert worker1.job == Job(boss=boss, boss_dbref=boss) | ||||
|         assert worker1.job == Job(boss=boss.id, boss_dbref=boss.id) | ||||
|  | ||||
|         # The above equalities should also hold after worker1.job.boss has been | ||||
|         # fetch()ed. | ||||
|         worker1.job.boss.fetch() | ||||
|         self.assertEqual(worker1.job, worker.job) | ||||
|         self.assertEqual(worker1.job, Job(boss=boss, boss_dbref=boss)) | ||||
|         self.assertEqual(worker1.job, Job(boss=boss.id, boss_dbref=boss.id)) | ||||
|         assert worker1.job == worker.job | ||||
|         assert worker1.job == Job(boss=boss, boss_dbref=boss) | ||||
|         assert worker1.job == Job(boss=boss.id, boss_dbref=boss.id) | ||||
|  | ||||
|     def test_dbref_equality(self): | ||||
|         class Test2(Document): | ||||
| @@ -3617,6 +3617,51 @@ class TestInstance(MongoDBTestCase): | ||||
|             assert b._instance == a | ||||
|         assert idx == 2 | ||||
|  | ||||
|     def test_updating_listfield_manipulate_list(self): | ||||
|         class Company(Document): | ||||
|             name = StringField() | ||||
|             employees = ListField(field=DictField()) | ||||
|  | ||||
|         Company.drop_collection() | ||||
|  | ||||
|         comp = Company(name="BigBank", employees=[{"name": "John"}]) | ||||
|         comp.save() | ||||
|         comp.employees.append({"name": "Bill"}) | ||||
|         comp.save() | ||||
|  | ||||
|         stored_comp = get_as_pymongo(comp) | ||||
|         self.assertEqual( | ||||
|             stored_comp, | ||||
|             { | ||||
|                 "_id": comp.id, | ||||
|                 "employees": [{"name": "John"}, {"name": "Bill"}], | ||||
|                 "name": "BigBank", | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
|         comp = comp.reload() | ||||
|         comp.employees[0]["color"] = "red" | ||||
|         comp.employees[-1]["color"] = "blue" | ||||
|         comp.employees[-1].update({"size": "xl"}) | ||||
|         comp.save() | ||||
|  | ||||
|         assert len(comp.employees) == 2 | ||||
|         assert comp.employees[0] == {"name": "John", "color": "red"} | ||||
|         assert comp.employees[1] == {"name": "Bill", "size": "xl", "color": "blue"} | ||||
|  | ||||
|         stored_comp = get_as_pymongo(comp) | ||||
|         self.assertEqual( | ||||
|             stored_comp, | ||||
|             { | ||||
|                 "_id": comp.id, | ||||
|                 "employees": [ | ||||
|                     {"name": "John", "color": "red"}, | ||||
|                     {"size": "xl", "color": "blue", "name": "Bill"}, | ||||
|                 ], | ||||
|                 "name": "BigBank", | ||||
|             }, | ||||
|         ) | ||||
|  | ||||
|     def test_falsey_pk(self): | ||||
|         """Ensure that we can create and update a document with Falsey PK.""" | ||||
|  | ||||
| @@ -3693,13 +3738,13 @@ class TestInstance(MongoDBTestCase): | ||||
|         value = u"I_should_be_a_dict" | ||||
|         coll.insert_one({"light_saber": value}) | ||||
|  | ||||
|         with self.assertRaises(InvalidDocumentError) as cm: | ||||
|         with pytest.raises(InvalidDocumentError) as exc_info: | ||||
|             list(Jedi.objects) | ||||
|  | ||||
|         self.assertEqual( | ||||
|             str(cm.exception), | ||||
|             "Invalid data to create a `Jedi` instance.\nField 'light_saber' - The source SON object needs to be of type 'dict' but a '%s' was found" | ||||
|             % type(value), | ||||
|         assert str( | ||||
|             exc_info.value | ||||
|         ) == "Invalid data to create a `Jedi` instance.\nField 'light_saber' - The source SON object needs to be of type 'dict' but a '%s' was found" % type( | ||||
|             value | ||||
|         ) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -151,7 +151,7 @@ class TestFileField(MongoDBTestCase): | ||||
|         result = StreamFile.objects.first() | ||||
|         assert streamfile == result | ||||
|         assert result.the_file.read() == text + more_text | ||||
|         # self.assertEqual(result.the_file.content_type, content_type) | ||||
|         # assert result.the_file.content_type == content_type | ||||
|         result.the_file.seek(0) | ||||
|         assert result.the_file.tell() == 0 | ||||
|         assert result.the_file.read(len(text)) == text | ||||
|   | ||||
		Reference in New Issue
	
	Block a user