Added to the docs, mostly the user guide
This commit is contained in:
		
							
								
								
									
										18
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.rst
									
									
									
									
									
								
							| @@ -1,8 +1,18 @@ | |||||||
|  | =========== | ||||||
| MongoEngine | MongoEngine | ||||||
| =========== | =========== | ||||||
| MongoEngine is an ORM-like layer on top of PyMongo. | :Info: MongoEngine is an ORM-like layer on top of PyMongo. | ||||||
|  | :Author: Harry Marr (http://github.com/hmarr) | ||||||
|  |  | ||||||
| Tutorial available at http://hmarr.com/mongoengine/ | About | ||||||
|  | ===== | ||||||
|  | MongoEngine is a Python Object-Document Mapper for working with MongoDB.  | ||||||
|  | Documentation available at http://hmarr.com/mongoengine/ -- there is currently  | ||||||
|  | a `tutorial <http://hmarr.com/mongoengine/tutorial.html>`_, a `user guide  | ||||||
|  | <http://hmarr.com/mongoengine/userguide.html>`_ and an `API reference | ||||||
|  | <http://hmarr.com/mongoengine/apireference.html>`_. | ||||||
|  |  | ||||||
| **Warning:** this software is still in development and should *not* be used | Dependencies | ||||||
| in production. | ============ | ||||||
|  | pymongo 1.1+ | ||||||
|  | sphinx (optional -- for documentation generation) | ||||||
|   | |||||||
| @@ -1,13 +1,14 @@ | |||||||
|  | ============= | ||||||
| API Reference | API Reference | ||||||
| ============= | ============= | ||||||
|  |  | ||||||
| Connecting | Connecting | ||||||
| ---------- | ========== | ||||||
|  |  | ||||||
| .. autofunction:: mongoengine.connect | .. autofunction:: mongoengine.connect | ||||||
|  |  | ||||||
| Documents | Documents | ||||||
| --------- | ========= | ||||||
|  |  | ||||||
| .. autoclass:: mongoengine.Document | .. autoclass:: mongoengine.Document | ||||||
|    :members: |    :members: | ||||||
| @@ -21,13 +22,13 @@ Documents | |||||||
|    :members: |    :members: | ||||||
|  |  | ||||||
| Querying | Querying | ||||||
| -------- | ======== | ||||||
|  |  | ||||||
| .. autoclass:: mongoengine.queryset.QuerySet | .. autoclass:: mongoengine.queryset.QuerySet | ||||||
|    :members: |    :members: | ||||||
|  |  | ||||||
| Fields | Fields | ||||||
| ------ | ====== | ||||||
|  |  | ||||||
| .. autoclass:: mongoengine.StringField | .. autoclass:: mongoengine.StringField | ||||||
|  |  | ||||||
|   | |||||||
| @@ -44,10 +44,11 @@ copyright = u'2009, Harry Marr' | |||||||
| # |version| and |release|, also used in various other places throughout the | # |version| and |release|, also used in various other places throughout the | ||||||
| # built documents. | # built documents. | ||||||
| # | # | ||||||
|  | import mongoengine | ||||||
| # The short X.Y version. | # The short X.Y version. | ||||||
| version = '0.1' | version = mongoengine.get_version() | ||||||
| # The full version, including alpha/beta/rc tags. | # The full version, including alpha/beta/rc tags. | ||||||
| release = '0.1' | release = mongoengine.get_release() | ||||||
|  |  | ||||||
| # The language for content autogenerated by Sphinx. Refer to documentation | # The language for content autogenerated by Sphinx. Refer to documentation | ||||||
| # for a list of supported languages. | # for a list of supported languages. | ||||||
| @@ -128,7 +129,7 @@ html_static_path = ['_static'] | |||||||
|  |  | ||||||
| # If true, SmartyPants will be used to convert quotes and dashes to | # If true, SmartyPants will be used to convert quotes and dashes to | ||||||
| # typographically correct entities. | # typographically correct entities. | ||||||
| #html_use_smartypants = True | html_use_smartypants = True | ||||||
|  |  | ||||||
| # Custom sidebar templates, maps document names to template names. | # Custom sidebar templates, maps document names to template names. | ||||||
| #html_sidebars = {} | #html_sidebars = {} | ||||||
|   | |||||||
| @@ -13,9 +13,9 @@ MongoDB. The source is available on | |||||||
| .. toctree:: | .. toctree:: | ||||||
|    :maxdepth: 2 |    :maxdepth: 2 | ||||||
|  |  | ||||||
|    tutorial.rst |    tutorial | ||||||
|    userguide.rst |    userguide | ||||||
|    apireference.rst |    apireference | ||||||
|  |  | ||||||
| Indices and tables | Indices and tables | ||||||
| ================== | ================== | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | ======== | ||||||
| Tutorial | Tutorial | ||||||
| ======== | ======== | ||||||
| This tutorial introduces **MongoEngine** by means of example --- we will walk | This tutorial introduces **MongoEngine** by means of example --- we will walk | ||||||
| @@ -10,7 +11,7 @@ focus on the data-modelling side of the application, leaving out a user | |||||||
| interface. | interface. | ||||||
|  |  | ||||||
| Getting started | Getting started | ||||||
| --------------- | =============== | ||||||
| Before we start, make sure that a copy of MongoDB is running in an accessible | Before we start, make sure that a copy of MongoDB is running in an accessible | ||||||
| location --- running it locally will be easier, but if that is not an option | location --- running it locally will be easier, but if that is not an option | ||||||
| then it may be run on a remote server. | then it may be run on a remote server. | ||||||
| @@ -27,7 +28,7 @@ database to use:: | |||||||
| For more information about connecting to MongoDB see :ref:`guide-connecting`. | For more information about connecting to MongoDB see :ref:`guide-connecting`. | ||||||
|  |  | ||||||
| Defining our documents | Defining our documents | ||||||
| ---------------------- | ====================== | ||||||
| MongoDB is *schemaless*, which means that no schema is enforced by the database | MongoDB is *schemaless*, which means that no schema is enforced by the database | ||||||
| --- we may add and remove fields however we want and MongoDB won't complain. | --- we may add and remove fields however we want and MongoDB won't complain. | ||||||
| This makes life a lot easier in many regards, especially when there is a change | This makes life a lot easier in many regards, especially when there is a change | ||||||
| @@ -46,7 +47,7 @@ specified tag.  Finally, it would be nice if **comments** could be added to | |||||||
| posts. We'll start with **users**, as the others are slightly more involved. | posts. We'll start with **users**, as the others are slightly more involved. | ||||||
|  |  | ||||||
| Users | Users | ||||||
| ^^^^^ | ----- | ||||||
| Just as if we were using a relational database with an ORM, we need to define | Just as if we were using a relational database with an ORM, we need to define | ||||||
| which fields a :class:`User` may have, and what their types will be:: | which fields a :class:`User` may have, and what their types will be:: | ||||||
|  |  | ||||||
| @@ -61,7 +62,7 @@ MongoDB --- this will only be enforced at the application level. Also, the User | |||||||
| documents will be stored in a MongoDB *collection* rather than a table. | documents will be stored in a MongoDB *collection* rather than a table. | ||||||
|  |  | ||||||
| Posts, Comments and Tags | Posts, Comments and Tags | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ------------------------ | ||||||
| Now we'll think about how to store the rest of the information. If we were | Now we'll think about how to store the rest of the information. If we were | ||||||
| using a relational database, we would most likely have a table of **posts**, a | using a relational database, we would most likely have a table of **posts**, a | ||||||
| table of **comments** and a table of **tags**.  To associate the comments with | table of **comments** and a table of **tags**.  To associate the comments with | ||||||
| @@ -73,7 +74,7 @@ several ways we can achieve this, but each of them have their problems --- none | |||||||
| of them stand out as particularly intuitive solutions. | of them stand out as particularly intuitive solutions. | ||||||
|  |  | ||||||
| Posts | Posts | ||||||
| """"" | ^^^^^ | ||||||
| But MongoDB *isn't* a relational database, so we're not going to do it that | But MongoDB *isn't* a relational database, so we're not going to do it that | ||||||
| way. As it turns out, we can use MongoDB's schemaless nature to provide us with | way. As it turns out, we can use MongoDB's schemaless nature to provide us with | ||||||
| a much nicer solution. We will store all of the posts in *one collection* --- | a much nicer solution. We will store all of the posts in *one collection* --- | ||||||
| @@ -99,12 +100,12 @@ this kind of modelling out of the box:: | |||||||
|         link_url = StringField() |         link_url = StringField() | ||||||
|  |  | ||||||
| We are storing a reference to the author of the posts using a | We are storing a reference to the author of the posts using a | ||||||
| :class:`mongoengine.ReferenceField` object. These are similar to foreign key | :class:`~mongoengine.ReferenceField` object. These are similar to foreign key | ||||||
| fields in traditional ORMs, and are automatically translated into references | fields in traditional ORMs, and are automatically translated into references | ||||||
| when they are saved, and dereferenced when they are loaded. | when they are saved, and dereferenced when they are loaded. | ||||||
|  |  | ||||||
| Tags | Tags | ||||||
| """" | ^^^^ | ||||||
| Now that we have our Post models figured out, how will we attach tags to them? | Now that we have our Post models figured out, how will we attach tags to them? | ||||||
| MongoDB allows us to store lists of items natively, so rather than having a | MongoDB allows us to store lists of items natively, so rather than having a | ||||||
| link table, we can just store a list of tags in each post. So, for both | link table, we can just store a list of tags in each post. So, for both | ||||||
| @@ -120,13 +121,13 @@ size of our database. So let's take a look that the code our modified | |||||||
|         author = ReferenceField(User) |         author = ReferenceField(User) | ||||||
|         tags = ListField(StringField(max_length=30)) |         tags = ListField(StringField(max_length=30)) | ||||||
|  |  | ||||||
| The :class:`mongoengine.ListField` object that is used to define a Post's tags | The :class:`~mongoengine.ListField` object that is used to define a Post's tags | ||||||
| takes a field object as its first argument --- this means that you can have | takes a field object as its first argument --- this means that you can have | ||||||
| lists of any type of field (including lists). Note that we don't need to | lists of any type of field (including lists). Note that we don't need to | ||||||
| modify the specialised post types as they all inherit from :class:`Post`. | modify the specialised post types as they all inherit from :class:`Post`. | ||||||
|  |  | ||||||
| Comments | Comments | ||||||
| """""""" | ^^^^^^^^ | ||||||
| A comment is typically associated with *one* post. In a relational database, to | A comment is typically associated with *one* post. In a relational database, to | ||||||
| display a post with its comments, we would have to retrieve the post from the | display a post with its comments, we would have to retrieve the post from the | ||||||
| database, then query the database again for the comments associated with the | database, then query the database again for the comments associated with the | ||||||
| @@ -152,7 +153,7 @@ We can then store a list of comment documents in our post document:: | |||||||
|         comments = ListField(EmbeddedDocumentField(Comment)) |         comments = ListField(EmbeddedDocumentField(Comment)) | ||||||
|  |  | ||||||
| Adding data to our Tumblelog | Adding data to our Tumblelog | ||||||
| ---------------------------- | ============================ | ||||||
| Now that we've defined how our documents will be structured, let's start adding | Now that we've defined how our documents will be structured, let's start adding | ||||||
| some documents to the database. Firstly, we'll need to create a :class:`User` | some documents to the database. Firstly, we'll need to create a :class:`User` | ||||||
| object:: | object:: | ||||||
| @@ -184,10 +185,10 @@ Note that if you change a field on a object that has already been saved, then | |||||||
| call :meth:`save` again, the document will be updated. | call :meth:`save` again, the document will be updated. | ||||||
|  |  | ||||||
| Accessing our data | Accessing our data | ||||||
| ------------------ | ================== | ||||||
| So now we've got a couple of posts in our database, how do we display them? | So now we've got a couple of posts in our database, how do we display them? | ||||||
| Each document class (i.e. any class that inherits either directly or indirectly | Each document class (i.e. any class that inherits either directly or indirectly | ||||||
| from :class:`mongoengine.Document`) has an :attr:`objects` attribute, which is | from :class:`~mongoengine.Document`) has an :attr:`objects` attribute, which is | ||||||
| used to access the documents in the database collection associated with that | used to access the documents in the database collection associated with that | ||||||
| class. So let's see how we can get our posts' titles:: | class. So let's see how we can get our posts' titles:: | ||||||
|  |  | ||||||
| @@ -195,7 +196,7 @@ class. So let's see how we can get our posts' titles:: | |||||||
|         print post.title |         print post.title | ||||||
|  |  | ||||||
| Retrieving type-specific information | Retrieving type-specific information | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ------------------------------------ | ||||||
| This will print the titles of our posts, one on each line. But What if we want | This will print the titles of our posts, one on each line. But What if we want | ||||||
| to access the type-specific data (link_url, content, etc.)? One way is simply | to access the type-specific data (link_url, content, etc.)? One way is simply | ||||||
| to use the :attr:`objects` attribute of a subclass of :class:`Post`:: | to use the :attr:`objects` attribute of a subclass of :class:`Post`:: | ||||||
| @@ -205,7 +206,7 @@ to use the :attr:`objects` attribute of a subclass of :class:`Post`:: | |||||||
|  |  | ||||||
| Using TextPost's :attr:`objects` attribute only returns documents that were | Using TextPost's :attr:`objects` attribute only returns documents that were | ||||||
| created using :class:`TextPost`. Actually, there is a more general rule here: | created using :class:`TextPost`. Actually, there is a more general rule here: | ||||||
| the :attr:`objects` attribute of any subclass of :class:`mongoengine.Document` | the :attr:`objects` attribute of any subclass of :class:`~mongoengine.Document` | ||||||
| only looks for documents that were created using that subclass or one of its | only looks for documents that were created using that subclass or one of its | ||||||
| subclasses. | subclasses. | ||||||
|  |  | ||||||
| @@ -233,20 +234,21 @@ This would print the title of each post, followed by the content if it was a | |||||||
| text post, and "Link: <url>" if it was a link post. | text post, and "Link: <url>" if it was a link post. | ||||||
|  |  | ||||||
| Searching our posts by tag | Searching our posts by tag | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -------------------------- | ||||||
| The :attr:`objects` attribute of a :class:`mongoengine.Document` is actually a | The :attr:`objects` attribute of a :class:`~mongoengine.Document` is actually a | ||||||
| :class:`mongoengine.QuerySet` object. This lazily queries the database only | :class:`~mongoengine.queryset.QuerySet` object. This lazily queries the | ||||||
| when you need the data. It may also be filtered to narrow down your query. | database only when you need the data. It may also be filtered to narrow down | ||||||
| Let's adjust our query so that only posts with the tag "mongodb" are returned:: | your query.  Let's adjust our query so that only posts with the tag "mongodb" | ||||||
|  | are returned:: | ||||||
|  |  | ||||||
|     for post in Post.objects(tags='mongodb'): |     for post in Post.objects(tags='mongodb'): | ||||||
|         print post.title |         print post.title | ||||||
|  |  | ||||||
| There are also methods available on :class:`mongoengine.QuerySet` objects that | There are also methods available on :class:`~mongoengine.queryset.QuerySet` | ||||||
| allow different results to be returned, for example, calling :meth:`first` on | objects that allow different results to be returned, for example, calling | ||||||
| the :attr:`objects` attribute will return a single document, the first matched | :meth:`first` on the :attr:`objects` attribute will return a single document, | ||||||
| by the query you provide. Aggregation functions may also be used on | the first matched by the query you provide. Aggregation functions may also be | ||||||
| :class:`mongoengine.QuerySet` objects:: | used on :class:`~mongoengine.queryset.QuerySet` objects:: | ||||||
|  |  | ||||||
|     num_posts = Post.objects(tags='mongodb').count() |     num_posts = Post.objects(tags='mongodb').count() | ||||||
|     print 'Found % posts with tag "mongodb"' % num_posts |     print 'Found % posts with tag "mongodb"' % num_posts | ||||||
|   | |||||||
| @@ -1,10 +1,11 @@ | |||||||
|  | ========== | ||||||
| User Guide | User Guide | ||||||
| ========== | ========== | ||||||
|  |  | ||||||
| .. _guide-connecting: | .. _guide-connecting: | ||||||
|  |  | ||||||
| Connecting to MongoDB | Connecting to MongoDB | ||||||
| --------------------- | ===================== | ||||||
| To connect to a running instance of :program:`mongod`, use the | To connect to a running instance of :program:`mongod`, use the | ||||||
| :func:`~mongoengine.connect` function. The first argument is the name of the | :func:`~mongoengine.connect` function. The first argument is the name of the | ||||||
| database to connect to. If the database does not exist, it will be created. If | database to connect to. If the database does not exist, it will be created. If | ||||||
| @@ -22,7 +23,7 @@ provide :attr:`host` and :attr:`port` arguments to | |||||||
|     connect('project1', host='192.168.1.35', port=12345) |     connect('project1', host='192.168.1.35', port=12345) | ||||||
|  |  | ||||||
| Defining documents | Defining documents | ||||||
| ------------------ | ================== | ||||||
| In MongoDB, a **document** is roughly equivalent to a **row** in an RDBMS. When | In MongoDB, a **document** is roughly equivalent to a **row** in an RDBMS. When | ||||||
| working with relational databases, rows are stored in **tables**, which have a | working with relational databases, rows are stored in **tables**, which have a | ||||||
| strict **schema** that the rows follow. MongoDB stores documents in | strict **schema** that the rows follow. MongoDB stores documents in | ||||||
| @@ -30,7 +31,7 @@ strict **schema** that the rows follow. MongoDB stores documents in | |||||||
| is enforced at a database level.  | is enforced at a database level.  | ||||||
|  |  | ||||||
| Defining a document's schema | Defining a document's schema | ||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ---------------------------- | ||||||
| MongoEngine allows you to define schemata for documents as this helps to reduce | MongoEngine allows you to define schemata for documents as this helps to reduce | ||||||
| coding errors, and allows for utility methods to be defined on fields which may | coding errors, and allows for utility methods to be defined on fields which may | ||||||
| be present.  | be present.  | ||||||
| @@ -47,7 +48,7 @@ objects** as class attributes to the document class:: | |||||||
|         date_modified = DateTimeField(default=datetime.now) |         date_modified = DateTimeField(default=datetime.now) | ||||||
|  |  | ||||||
| Fields | Fields | ||||||
| ^^^^^^ | ------ | ||||||
| By default, fields are not required. To make a field mandatory, set the | By default, fields are not required. To make a field mandatory, set the | ||||||
| :attr:`required` keyword argument of a field to ``True``. Fields also may have | :attr:`required` keyword argument of a field to ``True``. Fields also may have | ||||||
| validation constraints available (such as :attr:`max_length` in the example | validation constraints available (such as :attr:`max_length` in the example | ||||||
| @@ -60,12 +61,69 @@ are as follows: | |||||||
| * :class:`~mongoengine.IntField` | * :class:`~mongoengine.IntField` | ||||||
| * :class:`~mongoengine.FloatField` | * :class:`~mongoengine.FloatField` | ||||||
| * :class:`~mongoengine.DateTimeField` | * :class:`~mongoengine.DateTimeField` | ||||||
|  | * :class:`~mongoengine.ListField` | ||||||
| * :class:`~mongoengine.ObjectIdField` | * :class:`~mongoengine.ObjectIdField` | ||||||
| * :class:`~mongoengine.EmbeddedDocumentField` | * :class:`~mongoengine.EmbeddedDocumentField` | ||||||
| * :class:`~mongoengine.ReferenceField` | * :class:`~mongoengine.ReferenceField` | ||||||
|  |  | ||||||
|  | List fields | ||||||
|  | ^^^^^^^^^^^ | ||||||
|  | MongoDB allows the storage of lists of items. To add a list of items to a | ||||||
|  | :class:`~mongoengine.Document`, use the :class:`~mongoengine.ListField` field | ||||||
|  | type. :class:`~mongoengine.ListField` takes another field object as its first | ||||||
|  | argument, which specifies which type elements may be stored within the list:: | ||||||
|  |  | ||||||
|  |     class Page(Document): | ||||||
|  |         tags = ListField(StringField(max_length=50)) | ||||||
|  |  | ||||||
|  | Embedded documents | ||||||
|  | ^^^^^^^^^^^^^^^^^^ | ||||||
|  | MongoDB has the ability to embed documents within other documents. Schemata may | ||||||
|  | be defined for these embedded documents, just as they may be for regular | ||||||
|  | documents. To create an embedded document, just define a document as usual, but | ||||||
|  | inherit from :class:`~mongoengine.EmbeddedDocument` rather than  | ||||||
|  | :class:`~mongoengine.Document`:: | ||||||
|  |  | ||||||
|  |     class Comment(EmbeddedDocument): | ||||||
|  |         content = StringField() | ||||||
|  |  | ||||||
|  | To embed the document within another document, use the | ||||||
|  | :class:`~mongoengine.EmbeddedDocumentField` field type, providing the embedded | ||||||
|  | document class as the first argument:: | ||||||
|  |  | ||||||
|  |     class Page(Document): | ||||||
|  |         comments = ListField(EmbeddedDocumentField(Comment)) | ||||||
|  |  | ||||||
|  |     comment1 = Comment('Good work!') | ||||||
|  |     comment2 = Comment('Nice article!') | ||||||
|  |     page = Page(comments=[comment1, comment2]) | ||||||
|  |  | ||||||
|  | Reference fields | ||||||
|  | ^^^^^^^^^^^^^^^^ | ||||||
|  | References may be stored to other documents in the database using the | ||||||
|  | :class:`~mongoengine.ReferenceField`. Pass in another document class as the | ||||||
|  | first argument to the constructor, then simply assign document objects to the | ||||||
|  | field:: | ||||||
|  |      | ||||||
|  |     class User(Document): | ||||||
|  |         name = StringField() | ||||||
|  |  | ||||||
|  |     class Page(Document): | ||||||
|  |         content = StringField() | ||||||
|  |         author = ReferenceField(User) | ||||||
|  |  | ||||||
|  |     john = User(name="John Smith") | ||||||
|  |     john.save() | ||||||
|  |  | ||||||
|  |     post = Page(content="Test Page") | ||||||
|  |     post.author = john | ||||||
|  |     post.save() | ||||||
|  |  | ||||||
|  | The :class:`User` object is automatically turned into a reference behind the | ||||||
|  | scenes, and dereferenced when the :class:`Page` object is retrieved. | ||||||
|  |  | ||||||
| Document collections | Document collections | ||||||
| ^^^^^^^^^^^^^^^^^^^^ | -------------------- | ||||||
| Document classes that inherit **directly** from :class:`~mongoengine.Document` | Document classes that inherit **directly** from :class:`~mongoengine.Document` | ||||||
| will have their own **collection** in the database. The name of the collection | will have their own **collection** in the database. The name of the collection | ||||||
| is by default the name of the class, coverted to lowercase (so in the example | is by default the name of the class, coverted to lowercase (so in the example | ||||||
| @@ -78,3 +136,175 @@ document class to use:: | |||||||
|     class Page(Document): |     class Page(Document): | ||||||
|         title = StringField(max_length=200, required=True) |         title = StringField(max_length=200, required=True) | ||||||
|         meta = {'collection': 'cmsPage'} |         meta = {'collection': 'cmsPage'} | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  | :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:: | ||||||
|  |  | ||||||
|  |     # Stored in a collection named 'page' | ||||||
|  |     class Page(Document): | ||||||
|  |         title = StringField(max_length=200, required=True) | ||||||
|  |  | ||||||
|  |     # Also stored in the collection named 'page' | ||||||
|  |     class DatedPage(Page): | ||||||
|  |         date = DateTimeField() | ||||||
|  |  | ||||||
|  | Working with existing data | ||||||
|  | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||
|  | To enable correct retrieval of documents involved in this kind of heirarchy, | ||||||
|  | two extra attributes are stored on each document in the database: :attr:`_cls` | ||||||
|  | and :attr:`_types`. These are hidden from the user through the MongoEngine | ||||||
|  | interface, but may not be present if you are trying to use MongoEngine with  | ||||||
|  | an existing database. For this reason, you may disable this inheritance | ||||||
|  | mechansim, removing the dependency of :attr:`_cls` and :attr:`_types`, enabling | ||||||
|  | you to work with existing databases. To disable inheritance on a document | ||||||
|  | class, set :attr:`allow_inheritance` to ``False`` in the :attr:`meta` | ||||||
|  | dictionary:: | ||||||
|  |  | ||||||
|  |     # Will work with data in an existing collection named 'cmsPage' | ||||||
|  |     class Page(Document): | ||||||
|  |         title = StringField(max_length=200, required=True) | ||||||
|  |         meta = { | ||||||
|  |             'collection': 'cmsPage', | ||||||
|  |             'allow_inheritance': False, | ||||||
|  |         } | ||||||
|  |  | ||||||
|  | Documents instances | ||||||
|  | =================== | ||||||
|  | To create a new document object, create an instance of the relevant document | ||||||
|  | class, providing values for its fields as its constructor keyword arguments. | ||||||
|  | You may provide values for any of the fields on the document, but only | ||||||
|  | **required** fields are necessary at this stage:: | ||||||
|  |      | ||||||
|  |     >>> page = Page(title="Test Page") | ||||||
|  |     >>> page.title | ||||||
|  |     'Test Page' | ||||||
|  |  | ||||||
|  | You may also assign values to the document's fields using standard object  | ||||||
|  | attribute syntax:: | ||||||
|  |  | ||||||
|  |     >>> page.title = "Example Page" | ||||||
|  |     >>> page.title | ||||||
|  |     'Example Page' | ||||||
|  |  | ||||||
|  | Saving and deleting documents | ||||||
|  | ----------------------------- | ||||||
|  | To save the document to the database, call the | ||||||
|  | :meth:`~mongoengine.Document.save` method. If the document does not exist in | ||||||
|  | the database, it will be created. If it does already exist, it will be | ||||||
|  | updated. | ||||||
|  |  | ||||||
|  | To delete a document, call the :meth:`~mongoengine.Document.delete` method. | ||||||
|  | Note that this will only work if the document exists in the database and has a | ||||||
|  | valide :attr:`id`. | ||||||
|  |  | ||||||
|  | Document IDs | ||||||
|  | ------------ | ||||||
|  | Each document in the database has a unique id. This may be accessed through the | ||||||
|  | :attr:`id` attribute on :class:`~mongoengine.Document` objects. Usually, the id | ||||||
|  | will be generated automatically by the database server when the object is save, | ||||||
|  | meaning that you may only access the :attr:`id` field once a document has been | ||||||
|  | saved:: | ||||||
|  |  | ||||||
|  |     >>> page = Page(title="Test Page") | ||||||
|  |     >>> page.id | ||||||
|  |     ... | ||||||
|  |     AttributeError('_id') | ||||||
|  |     >>> page.save() | ||||||
|  |     >>> page.id | ||||||
|  |     ObjectId('123456789abcdef000000000') | ||||||
|  |  | ||||||
|  | Alternatively, you may explicitly set the :attr:`id` before you save the | ||||||
|  | document, but the id must be a valid PyMongo :class:`ObjectId`. | ||||||
|  |  | ||||||
|  | Querying the database | ||||||
|  | ===================== | ||||||
|  | :class:`~mongoengine.Document` classes have an :attr:`objects` attribute, which | ||||||
|  | is used for accessing the objects in the database associated with the class. | ||||||
|  | The :attr:`objects` attribute is actually a | ||||||
|  | :class:`~mongoengine.queryset.QuerySetManager`, which creates and returns a new | ||||||
|  | a new :class:`~mongoengine.queryset.QuerySet` object on access. The | ||||||
|  | :class:`~mongoengine.queryset.QuerySet` object may may be iterated over to | ||||||
|  | fetch documents from the database:: | ||||||
|  |  | ||||||
|  |     # Prints out the names of all the users in the database | ||||||
|  |     for user in User.objects: | ||||||
|  |         print user.name | ||||||
|  |  | ||||||
|  | Filtering queries | ||||||
|  | ----------------- | ||||||
|  | The query may be filtered by calling the | ||||||
|  | :class:`~mongoengine.queryset.QuerySet` object with field lookup keyword  | ||||||
|  | arguments. The keys in the keyword arguments correspond to fields on the | ||||||
|  | :class:`~mongoengine.Document` you are querying:: | ||||||
|  |  | ||||||
|  |     # This will return a QuerySet that will only iterate over users whose | ||||||
|  |     # 'country' field is set to 'uk' | ||||||
|  |     uk_users = User.objects(country='uk') | ||||||
|  |  | ||||||
|  | Fields on embedded documents may also be referred to using field lookup syntax | ||||||
|  | by using a double-underscore in place of the dot in object attribute access | ||||||
|  | syntax:: | ||||||
|  |      | ||||||
|  |     # This will return a QuerySet that will only iterate over pages that have | ||||||
|  |     # been written by a user whose 'country' field is set to 'uk' | ||||||
|  |     uk_pages = Page.objects(author__country='uk') | ||||||
|  |  | ||||||
|  | Querying lists | ||||||
|  | ^^^^^^^^^^^^^^ | ||||||
|  | On most fields, this syntax will look up documents where the field specified | ||||||
|  | matches the given value exactly, but when the field refers to a | ||||||
|  | :class:`~mongoengine.ListField`, a single item may be provided, in which case | ||||||
|  | lists that contain that item will be matched:: | ||||||
|  |  | ||||||
|  |     class Page(Document): | ||||||
|  |         tags = ListField(StringField()) | ||||||
|  |  | ||||||
|  |     # This will match all pages that have the word 'coding' as an item in the | ||||||
|  |     # 'tags' list | ||||||
|  |     Page.objects(tags='coding') | ||||||
|  |  | ||||||
|  | Query operators | ||||||
|  | --------------- | ||||||
|  | Operators other than equality may also be used in queries; just attach the | ||||||
|  | operator name to a key with a double-underscore:: | ||||||
|  |      | ||||||
|  |     # Only find users whose age is 18 or less | ||||||
|  |     young_users = Users.objects(age__lte=18) | ||||||
|  |  | ||||||
|  | Available operators are as follows: | ||||||
|  |  | ||||||
|  | * ``neq`` -- not equal to | ||||||
|  | * ``lt`` -- less than | ||||||
|  | * ``lte`` -- less than or equal to | ||||||
|  | * ``gt`` -- greater than | ||||||
|  | * ``gte`` -- greater than or equal to | ||||||
|  | * ``in`` -- value is in list (a list of values should be provided) | ||||||
|  | * ``nin`` -- value is not in list (a list of values should be provided) | ||||||
|  | * ``mod`` -- ``value % x == y``, where ``x`` and ``y`` are two provided values | ||||||
|  | * ``all`` -- every item in array is in list of values provided | ||||||
|  | * ``size`` -- the size of the array is  | ||||||
|  | * ``exists`` -- value for field exists | ||||||
|  |  | ||||||
|  | Limiting and skipping results | ||||||
|  | ----------------------------- | ||||||
|  | Just as with traditional ORMs, you may limit the number of results returned, or | ||||||
|  | skip a number or results in you query. | ||||||
|  | :meth:`mongoengine.queryset.QuerySet.limit` and | ||||||
|  | :meth:`mongoengine.queryset.QuerySet.skip` and methods are available on | ||||||
|  | :meth:`mongoengine.queryset.QuerySet` objects, but the prefered syntax for | ||||||
|  | achieving this is using array-slicing syntax:: | ||||||
|  |  | ||||||
|  |     # Only the first 5 people | ||||||
|  |     users = User.objects[:5] | ||||||
|  |  | ||||||
|  |     # All except for the first 5 people | ||||||
|  |     users = User.objects[5:] | ||||||
|  |  | ||||||
|  |     # 5 users, starting from the 10th user found | ||||||
|  |     users = User.objects[10:15] | ||||||
|   | |||||||
| @@ -8,5 +8,20 @@ from connection import * | |||||||
| __all__ = document.__all__ + fields.__all__ + connection.__all__ | __all__ = document.__all__ + fields.__all__ + connection.__all__ | ||||||
|  |  | ||||||
| __author__ = 'Harry Marr' | __author__ = 'Harry Marr' | ||||||
| __version__ = '0.1' |  | ||||||
|  | VERSION = (0, 1, 0, 'alpha') | ||||||
|  |  | ||||||
|  | def get_version(): | ||||||
|  |     version = '%s.%s' % (VERSION[0], VERSION[1]) | ||||||
|  |     if VERSION[2]: | ||||||
|  |         version = '%s.%s' % (version, VERSION[2]) | ||||||
|  |     return version | ||||||
|  |  | ||||||
|  | def get_release(): | ||||||
|  |     version = get_version() | ||||||
|  |     if VERSION[3] != 'final': | ||||||
|  |         version = '%s-%s' % (version, VERSION[3]) | ||||||
|  |     return version | ||||||
|  |  | ||||||
|  | __version__ = get_release() | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user