fixed merge conflict in queryset test
This commit is contained in:
@@ -46,6 +46,8 @@ Fields
|
||||
|
||||
.. autoclass:: mongoengine.EmbeddedDocumentField
|
||||
|
||||
.. autoclass:: mongoengine.DictField
|
||||
|
||||
.. autoclass:: mongoengine.ListField
|
||||
|
||||
.. autoclass:: mongoengine.ObjectIdField
|
||||
|
||||
@@ -39,12 +39,13 @@ are as follows:
|
||||
* :class:`~mongoengine.FloatField`
|
||||
* :class:`~mongoengine.DateTimeField`
|
||||
* :class:`~mongoengine.ListField`
|
||||
* :class:`~mongoengine.DictField`
|
||||
* :class:`~mongoengine.ObjectIdField`
|
||||
* :class:`~mongoengine.EmbeddedDocumentField`
|
||||
* :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
|
||||
@@ -54,7 +55,7 @@ argument, which specifies which type elements may be stored within the list::
|
||||
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
|
||||
@@ -75,8 +76,25 @@ document class as the first argument::
|
||||
comment2 = Comment('Nice article!')
|
||||
page = Page(comments=[comment1, comment2])
|
||||
|
||||
Dictionary Fields
|
||||
-----------------
|
||||
Often, an embedded document may be used instead of a dictionary -- generally
|
||||
this is recommended as dictionaries don't support validation or custom field
|
||||
types. However, sometimes you will not know the structure of what you want to
|
||||
store; in this situation a :class:`~mongoengine.DictField` is appropriate::
|
||||
|
||||
class SurveyResponse(Document):
|
||||
date = DateTimeField()
|
||||
user = ReferenceField(User)
|
||||
answers = DictField()
|
||||
|
||||
survey_response = SurveyResponse(date=datetime.now(), user=request.user)
|
||||
response_form = ResponseForm(request.POST)
|
||||
survey_response.answers = response_form.cleaned_data()
|
||||
survey_response.save()
|
||||
|
||||
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
|
||||
@@ -100,7 +118,7 @@ The :class:`User` object is automatically turned into a reference behind the
|
||||
scenes, and dereferenced when the :class:`Page` object is retrieved.
|
||||
|
||||
Uniqueness constraints
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
----------------------
|
||||
MongoEngine allows you to specify that a field should be unique across a
|
||||
collection by providing ``unique=True`` to a :class:`~mongoengine.Field`\ 's
|
||||
constructor. If you try to save a document that has the same value for a unique
|
||||
@@ -130,7 +148,7 @@ document class to use::
|
||||
meta = {'collection': 'cmsPage'}
|
||||
|
||||
Capped collections
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
------------------
|
||||
A :class:`~mongoengine.Document` may use a **Capped Collection** by specifying
|
||||
:attr:`max_documents` and :attr:`max_size` in the :attr:`meta` dictionary.
|
||||
:attr:`max_documents` is the maximum number of documents that is allowed to be
|
||||
@@ -179,13 +197,13 @@ subsequent calls to :meth:`~mongoengine.queryset.QuerySet.order_by`. ::
|
||||
}
|
||||
|
||||
blog_post_1 = BlogPost(title="Blog Post #1")
|
||||
blog_post_1.published_date = datetime(2010, 1, 5, 0, 0 ,0))
|
||||
blog_post_1.published_date = datetime(2010, 1, 5, 0, 0 ,0)
|
||||
|
||||
blog_post_2 = BlogPost(title="Blog Post #2")
|
||||
blog_post_2.published_date = datetime(2010, 1, 6, 0, 0 ,0))
|
||||
blog_post_2.published_date = datetime(2010, 1, 6, 0, 0 ,0)
|
||||
|
||||
blog_post_3 = BlogPost(title="Blog Post #3")
|
||||
blog_post_3.published_date = datetime(2010, 1, 7, 0, 0 ,0))
|
||||
blog_post_3.published_date = datetime(2010, 1, 7, 0, 0 ,0)
|
||||
|
||||
blog_post_1.save()
|
||||
blog_post_2.save()
|
||||
@@ -194,11 +212,11 @@ subsequent calls to :meth:`~mongoengine.queryset.QuerySet.order_by`. ::
|
||||
# get the "first" BlogPost using default ordering
|
||||
# from BlogPost.meta.ordering
|
||||
latest_post = BlogPost.objects.first()
|
||||
self.assertEqual(latest_post.title, "Blog Post #3")
|
||||
assert latest_post.title == "Blog Post #3"
|
||||
|
||||
# override default ordering, order BlogPosts by "published_date"
|
||||
first_post = BlogPost.objects.order_by("+published_date").first()
|
||||
self.assertEqual(first_post.title, "Blog Post #1")
|
||||
assert first_post.title == "Blog Post #1"
|
||||
|
||||
Document inheritance
|
||||
====================
|
||||
@@ -218,7 +236,7 @@ convenient and efficient retrieval of related documents::
|
||||
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
|
||||
|
||||
@@ -17,7 +17,7 @@ attribute syntax::
|
||||
'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
|
||||
@@ -31,7 +31,7 @@ valide :attr:`id`.
|
||||
:ref:`guide-atomic-updates`
|
||||
|
||||
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,
|
||||
|
||||
@@ -14,7 +14,7 @@ fetch documents from the database::
|
||||
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
|
||||
@@ -33,7 +33,7 @@ syntax::
|
||||
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
|
||||
@@ -47,7 +47,7 @@ lists that contain that item will be matched::
|
||||
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::
|
||||
|
||||
@@ -69,7 +69,7 @@ Available operators are as follows:
|
||||
* ``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
|
||||
@@ -86,15 +86,89 @@ achieving this is using array-slicing syntax::
|
||||
# 5 users, starting from the 10th user found
|
||||
users = User.objects[10:15]
|
||||
|
||||
You may also index the query to retrieve a single result. If an item at that
|
||||
index does not exists, an :class:`IndexError` will be raised. A shortcut for
|
||||
retrieving the first result and returning :attr:`None` if no result exists is
|
||||
provided (:meth:`~mongoengine.queryset.QuerySet.first`)::
|
||||
|
||||
>>> # Make sure there are no users
|
||||
>>> User.drop_collection()
|
||||
>>> User.objects[0]
|
||||
IndexError: list index out of range
|
||||
>>> User.objects.first() == None
|
||||
True
|
||||
>>> User(name='Test User').save()
|
||||
>>> User.objects[0] == User.objects.first()
|
||||
True
|
||||
|
||||
Retrieving unique results
|
||||
-------------------------
|
||||
To retrieve a result that should be unique in the collection, use
|
||||
:meth:`~mongoengine.queryset.QuerySet.get`. This will raise
|
||||
:class:`~mongoengine.queryset.DoesNotExist` if no document matches the query,
|
||||
and :class:`~mongoengine.queryset.MultipleObjectsReturned` if more than one
|
||||
document matched the query.
|
||||
|
||||
A variation of this method exists,
|
||||
:meth:`~mongoengine.queryset.Queryset.get_or_create`, that will create a new
|
||||
document with the query arguments if no documents match the query. An
|
||||
additional keyword argument, :attr:`defaults` may be provided, which will be
|
||||
used as default values for the new document, in the case that it should need
|
||||
to be created::
|
||||
|
||||
>>> a = User.objects.get_or_create(name='User A', defaults={'age': 30})
|
||||
>>> b = User.objects.get_or_create(name='User A', defaults={'age': 40})
|
||||
>>> a.name == b.name and a.age == b.age
|
||||
True
|
||||
|
||||
Default Document queries
|
||||
========================
|
||||
By default, the objects :attr:`~mongoengine.Document.objects` attribute on a
|
||||
document returns a :class:`~mongoengine.queryset.QuerySet` that doesn't filter
|
||||
the collection -- it returns all objects. This may be changed by defining a
|
||||
method on a document that modifies a queryset. The method should accept two
|
||||
arguments -- :attr:`doc_cls` and :attr:`queryset`. The first argument is the
|
||||
:class:`~mongoengine.Document` class that the method is defined on (in this
|
||||
sense, the method is more like a :func:`classmethod` than a regular method),
|
||||
and the second argument is the initial queryset. The method needs to be
|
||||
decorated with :func:`~mongoengine.queryset.queryset_manager` in order for it
|
||||
to be recognised. ::
|
||||
|
||||
class BlogPost(Document):
|
||||
title = StringField()
|
||||
date = DateTimeField()
|
||||
|
||||
@queryset_manager
|
||||
def objects(doc_cls, queryset):
|
||||
# This may actually also be done by defining a default ordering for
|
||||
# the document, but this illustrates the use of manager methods
|
||||
return queryset.order_by('-date')
|
||||
|
||||
You don't need to call your method :attr:`objects` -- you may define as many
|
||||
custom manager methods as you like::
|
||||
|
||||
class BlogPost(Document):
|
||||
title = StringField()
|
||||
published = BooleanField()
|
||||
|
||||
@queryset_manager
|
||||
def live_posts(doc_cls, queryset):
|
||||
return queryset.order_by('-date')
|
||||
|
||||
BlogPost(title='test1', published=False).save()
|
||||
BlogPost(title='test2', published=True).save()
|
||||
assert len(BlogPost.objects) == 2
|
||||
assert len(BlogPost.live_posts) == 1
|
||||
|
||||
Aggregation
|
||||
-----------
|
||||
===========
|
||||
MongoDB provides some aggregation methods out of the box, but there are not as
|
||||
many as you typically get with an RDBMS. MongoEngine provides a wrapper around
|
||||
the built-in methods and provides some of its own, which are implemented as
|
||||
Javascript code that is executed on the database server.
|
||||
|
||||
Counting results
|
||||
^^^^^^^^^^^^^^^^
|
||||
----------------
|
||||
Just as with limiting and skipping results, there is a method on
|
||||
:class:`~mongoengine.queryset.QuerySet` objects --
|
||||
:meth:`~mongoengine.queryset.QuerySet.count`, but there is also a more Pythonic
|
||||
@@ -103,7 +177,7 @@ way of achieving this::
|
||||
num_users = len(User.objects)
|
||||
|
||||
Further aggregation
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
-------------------
|
||||
You may sum over the values of a specific field on documents using
|
||||
:meth:`~mongoengine.queryset.QuerySet.sum`::
|
||||
|
||||
@@ -133,7 +207,7 @@ would be generating "tag-clouds"::
|
||||
top_tags = sorted(tag_freqs.items(), key=itemgetter(1), reverse=True)[:10]
|
||||
|
||||
Advanced queries
|
||||
----------------
|
||||
================
|
||||
Sometimes calling a :class:`~mongoengine.queryset.QuerySet` object with keyword
|
||||
arguments can't fully express the query you want to use -- for example if you
|
||||
need to combine a number of constraints using *and* and *or*. This is made
|
||||
@@ -161,7 +235,7 @@ calling it with keyword arguments::
|
||||
.. _guide-atomic-updates:
|
||||
|
||||
Atomic updates
|
||||
--------------
|
||||
==============
|
||||
Documents may be updated atomically by using the
|
||||
:meth:`~mongoengine.queryset.QuerySet.update_one` and
|
||||
:meth:`~mongoengine.queryset.QuerySet.update` methods on a
|
||||
|
||||
@@ -11,6 +11,11 @@ MongoDB. To install it, simply run
|
||||
|
||||
The source is available on `GitHub <http://github.com/hmarr/mongoengine>`_.
|
||||
|
||||
If you are interested in contributing, join the developers' `mailing list
|
||||
<http://groups.google.com/group/mongoengine-dev>`_. Some of us also like to
|
||||
hang out at `#mongoengine IRC channel <irc://irc.freenode.net/mongoengine>`_.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
Reference in New Issue
Block a user