Compare commits
9 Commits
ci-test-ag
...
cleanup-qs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
160379ea85 | ||
|
|
e8ea294964 | ||
|
|
19ef2be88b | ||
|
|
30e8b8186f | ||
|
|
741643af5f | ||
|
|
398964945a | ||
|
|
5f43c032f2 | ||
|
|
627cf90de0 | ||
|
|
2bedb36d7f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,3 +17,4 @@ tests/test_bugfix.py
|
|||||||
htmlcov/
|
htmlcov/
|
||||||
venv
|
venv
|
||||||
venv3
|
venv3
|
||||||
|
scratchpad
|
||||||
|
|||||||
@@ -42,13 +42,18 @@ the :attr:`host` to
|
|||||||
will establish connection to ``production`` database using
|
will establish connection to ``production`` database using
|
||||||
``admin`` username and ``qwerty`` password.
|
``admin`` username and ``qwerty`` password.
|
||||||
|
|
||||||
ReplicaSets
|
Replica Sets
|
||||||
===========
|
============
|
||||||
|
|
||||||
MongoEngine supports
|
MongoEngine supports connecting to replica sets::
|
||||||
:class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient`. To use them,
|
|
||||||
please use an URI style connection and provide the ``replicaSet`` name
|
from mongoengine import connect
|
||||||
in the connection kwargs.
|
|
||||||
|
# Regular connect
|
||||||
|
connect('dbname', replicaset='rs-name')
|
||||||
|
|
||||||
|
# MongoDB URI-style connect
|
||||||
|
connect(host='mongodb://localhost/dbname?replicaSet=rs-name')
|
||||||
|
|
||||||
Read preferences are supported through the connection or via individual
|
Read preferences are supported through the connection or via individual
|
||||||
queries by passing the read_preference ::
|
queries by passing the read_preference ::
|
||||||
@@ -59,76 +64,74 @@ queries by passing the read_preference ::
|
|||||||
Multiple Databases
|
Multiple Databases
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Multiple database support was added in MongoEngine 0.6. To use multiple
|
To use multiple databases you can use :func:`~mongoengine.connect` and provide
|
||||||
databases you can use :func:`~mongoengine.connect` and provide an `alias` name
|
an `alias` name for the connection - if no `alias` is provided then "default"
|
||||||
for the connection - if no `alias` is provided then "default" is used.
|
is used.
|
||||||
|
|
||||||
In the background this uses :func:`~mongoengine.register_connection` to
|
In the background this uses :func:`~mongoengine.register_connection` to
|
||||||
store the data and you can register all aliases up front if required.
|
store the data and you can register all aliases up front if required.
|
||||||
|
|
||||||
Individual documents can also support multiple databases by providing a
|
Individual documents can also support multiple databases by providing a
|
||||||
`db_alias` in their meta data. This allows :class:`~pymongo.dbref.DBRef` objects
|
`db_alias` in their meta data. This allows :class:`~pymongo.dbref.DBRef`
|
||||||
to point across databases and collections. Below is an example schema, using
|
objects to point across databases and collections. Below is an example schema,
|
||||||
3 different databases to store data::
|
using 3 different databases to store data::
|
||||||
|
|
||||||
class User(Document):
|
class User(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
meta = {"db_alias": "user-db"}
|
meta = {'db_alias': 'user-db'}
|
||||||
|
|
||||||
class Book(Document):
|
class Book(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
meta = {"db_alias": "book-db"}
|
meta = {'db_alias': 'book-db'}
|
||||||
|
|
||||||
class AuthorBooks(Document):
|
class AuthorBooks(Document):
|
||||||
author = ReferenceField(User)
|
author = ReferenceField(User)
|
||||||
book = ReferenceField(Book)
|
book = ReferenceField(Book)
|
||||||
|
|
||||||
meta = {"db_alias": "users-books-db"}
|
meta = {'db_alias': 'users-books-db'}
|
||||||
|
|
||||||
|
|
||||||
Context Managers
|
Context Managers
|
||||||
================
|
================
|
||||||
Sometimes you may want to switch the database or collection to query against
|
Sometimes you may want to switch the database or collection to query against.
|
||||||
for a class.
|
|
||||||
For example, archiving older data into a separate database for performance
|
For example, archiving older data into a separate database for performance
|
||||||
reasons or writing functions that dynamically choose collections to write
|
reasons or writing functions that dynamically choose collections to write
|
||||||
document to.
|
a document to.
|
||||||
|
|
||||||
Switch Database
|
Switch Database
|
||||||
---------------
|
---------------
|
||||||
The :class:`~mongoengine.context_managers.switch_db` context manager allows
|
The :class:`~mongoengine.context_managers.switch_db` context manager allows
|
||||||
you to change the database alias for a given class allowing quick and easy
|
you to change the database alias for a given class allowing quick and easy
|
||||||
access the same User document across databases::
|
access to the same User document across databases::
|
||||||
|
|
||||||
from mongoengine.context_managers import switch_db
|
from mongoengine.context_managers import switch_db
|
||||||
|
|
||||||
class User(Document):
|
class User(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
meta = {"db_alias": "user-db"}
|
meta = {'db_alias': 'user-db'}
|
||||||
|
|
||||||
with switch_db(User, 'archive-user-db') as User:
|
with switch_db(User, 'archive-user-db') as User:
|
||||||
User(name="Ross").save() # Saves the 'archive-user-db'
|
User(name='Ross').save() # Saves the 'archive-user-db'
|
||||||
|
|
||||||
|
|
||||||
Switch Collection
|
Switch Collection
|
||||||
-----------------
|
-----------------
|
||||||
The :class:`~mongoengine.context_managers.switch_collection` context manager
|
The :class:`~mongoengine.context_managers.switch_collection` context manager
|
||||||
allows you to change the collection for a given class allowing quick and easy
|
allows you to change the collection for a given class allowing quick and easy
|
||||||
access the same Group document across collection::
|
access to the same Group document across collection::
|
||||||
|
|
||||||
from mongoengine.context_managers import switch_collection
|
from mongoengine.context_managers import switch_collection
|
||||||
|
|
||||||
class Group(Document):
|
class Group(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
Group(name="test").save() # Saves in the default db
|
Group(name='test').save() # Saves in the default db
|
||||||
|
|
||||||
with switch_collection(Group, 'group2000') as Group:
|
with switch_collection(Group, 'group2000') as Group:
|
||||||
Group(name="hello Group 2000 collection!").save() # Saves in group2000 collection
|
Group(name='hello Group 2000 collection!').save() # Saves in group2000 collection
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. note:: Make sure any aliases have been registered with
|
.. note:: Make sure any aliases have been registered with
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
Installing MongoEngine
|
Installing MongoEngine
|
||||||
======================
|
======================
|
||||||
|
|
||||||
To use MongoEngine, you will need to download `MongoDB <http://mongodb.org/>`_
|
To use MongoEngine, you will need to download `MongoDB <http://mongodb.com/>`_
|
||||||
and ensure it is running in an accessible location. You will also need
|
and ensure it is running in an accessible location. You will also need
|
||||||
`PyMongo <http://api.mongodb.org/python>`_ to use MongoEngine, but if you
|
`PyMongo <http://api.mongodb.org/python>`_ to use MongoEngine, but if you
|
||||||
install MongoEngine using setuptools, then the dependencies will be handled for
|
install MongoEngine using setuptools, then the dependencies will be handled for
|
||||||
you.
|
you.
|
||||||
|
|
||||||
MongoEngine is available on PyPI, so to use it you can use :program:`pip`:
|
MongoEngine is available on PyPI, so you can use :program:`pip`:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
|
|||||||
@@ -340,14 +340,19 @@ Javascript code that is executed on the database server.
|
|||||||
|
|
||||||
Counting results
|
Counting results
|
||||||
----------------
|
----------------
|
||||||
Just as with limiting and skipping results, there is a method on
|
Just as with limiting and skipping results, there is a method on a
|
||||||
:class:`~mongoengine.queryset.QuerySet` objects --
|
:class:`~mongoengine.queryset.QuerySet` object --
|
||||||
:meth:`~mongoengine.queryset.QuerySet.count`, but there is also a more Pythonic
|
:meth:`~mongoengine.queryset.QuerySet.count`::
|
||||||
way of achieving this::
|
|
||||||
|
|
||||||
num_users = len(User.objects)
|
num_users = User.objects.count()
|
||||||
|
|
||||||
Even if len() is the Pythonic way of counting results, keep in mind that if you concerned about performance, :meth:`~mongoengine.queryset.QuerySet.count` is the way to go since it only execute a server side count query, while len() retrieves the results, places them in cache, and finally counts them. If we compare the performance of the two operations, len() is much slower than :meth:`~mongoengine.queryset.QuerySet.count`.
|
You could technically use ``len(User.objects)`` to get the same result, but it
|
||||||
|
would be significantly slower than :meth:`~mongoengine.queryset.QuerySet.count`.
|
||||||
|
When you execute a server-side count query, you let MongoDB do the heavy
|
||||||
|
lifting and you receive a single integer over the wire. Meanwhile, len()
|
||||||
|
retrieves all the results, places them in a local cache, and finally counts
|
||||||
|
them. If we compare the performance of the two operations, len() is much slower
|
||||||
|
than :meth:`~mongoengine.queryset.QuerySet.count`.
|
||||||
|
|
||||||
Further aggregation
|
Further aggregation
|
||||||
-------------------
|
-------------------
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ Tutorial
|
|||||||
========
|
========
|
||||||
|
|
||||||
This tutorial introduces **MongoEngine** by means of example --- we will walk
|
This tutorial introduces **MongoEngine** by means of example --- we will walk
|
||||||
through how to create a simple **Tumblelog** application. A Tumblelog is a type
|
through how to create a simple **Tumblelog** application. A tumblelog is a
|
||||||
of blog where posts are not constrained to being conventional text-based posts.
|
blog that supports mixed media content, including text, images, links, video,
|
||||||
As well as text-based entries, users may post images, links, videos, etc. For
|
audio, etc. For simplicity's sake, we'll stick to text, image, and link
|
||||||
simplicity's sake, we'll stick to text, image and link entries in our
|
entries. As the purpose of this tutorial is to introduce MongoEngine, we'll
|
||||||
application. As the purpose of this tutorial is to introduce MongoEngine, we'll
|
|
||||||
focus on the data-modelling side of the application, leaving out a user
|
focus on the data-modelling side of the application, leaving out a user
|
||||||
interface.
|
interface.
|
||||||
|
|
||||||
@@ -16,14 +15,14 @@ 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. If you haven't installed mongoengine,
|
then it may be run on a remote server. If you haven't installed MongoEngine,
|
||||||
simply use pip to install it like so::
|
simply use pip to install it like so::
|
||||||
|
|
||||||
$ pip install mongoengine
|
$ pip install mongoengine
|
||||||
|
|
||||||
Before we can start using MongoEngine, we need to tell it how to connect to our
|
Before we can start using MongoEngine, we need to tell it how to connect to our
|
||||||
instance of :program:`mongod`. For this we use the :func:`~mongoengine.connect`
|
instance of :program:`mongod`. For this we use the :func:`~mongoengine.connect`
|
||||||
function. If running locally the only argument we need to provide is the name
|
function. If running locally, the only argument we need to provide is the name
|
||||||
of the MongoDB database to use::
|
of the MongoDB database to use::
|
||||||
|
|
||||||
from mongoengine import *
|
from mongoengine import *
|
||||||
@@ -39,8 +38,8 @@ 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
|
||||||
to the data model. However, defining schemata for our documents can help to
|
to the data model. However, defining schemas for our documents can help to iron
|
||||||
iron out bugs involving incorrect types or missing fields, and also allow us to
|
out bugs involving incorrect types or missing fields, and also allow us to
|
||||||
define utility methods on our documents in the same way that traditional
|
define utility methods on our documents in the same way that traditional
|
||||||
:abbr:`ORMs (Object-Relational Mappers)` do.
|
:abbr:`ORMs (Object-Relational Mappers)` do.
|
||||||
|
|
||||||
@@ -96,7 +95,7 @@ using* the new fields we need to support video posts. This fits with the
|
|||||||
Object-Oriented principle of *inheritance* nicely. We can think of
|
Object-Oriented principle of *inheritance* nicely. We can think of
|
||||||
:class:`Post` as a base class, and :class:`TextPost`, :class:`ImagePost` and
|
:class:`Post` as a base class, and :class:`TextPost`, :class:`ImagePost` and
|
||||||
:class:`LinkPost` as subclasses of :class:`Post`. In fact, MongoEngine supports
|
:class:`LinkPost` as subclasses of :class:`Post`. In fact, MongoEngine supports
|
||||||
this kind of modelling out of the box --- all you need do is turn on inheritance
|
this kind of modeling out of the box --- all you need do is turn on inheritance
|
||||||
by setting :attr:`allow_inheritance` to True in the :attr:`meta`::
|
by setting :attr:`allow_inheritance` to True in the :attr:`meta`::
|
||||||
|
|
||||||
class Post(Document):
|
class Post(Document):
|
||||||
@@ -128,8 +127,8 @@ link table, we can just store a list of tags in each post. So, for both
|
|||||||
efficiency and simplicity's sake, we'll store the tags as strings directly
|
efficiency and simplicity's sake, we'll store the tags as strings directly
|
||||||
within the post, rather than storing references to tags in a separate
|
within the post, rather than storing references to tags in a separate
|
||||||
collection. Especially as tags are generally very short (often even shorter
|
collection. Especially as tags are generally very short (often even shorter
|
||||||
than a document's id), this denormalisation won't impact very strongly on the
|
than a document's id), this denormalization won't impact the size of the
|
||||||
size of our database. So let's take a look that the code our modified
|
database very strongly. Let's take a look at the code of our modified
|
||||||
:class:`Post` class::
|
:class:`Post` class::
|
||||||
|
|
||||||
class Post(Document):
|
class Post(Document):
|
||||||
@@ -141,7 +140,7 @@ The :class:`~mongoengine.fields.ListField` object that is used to define a Post'
|
|||||||
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).
|
lists of any type of field (including lists).
|
||||||
|
|
||||||
.. note:: We don't need to modify the specialised post types as they all
|
.. note:: We don't need to modify the specialized post types as they all
|
||||||
inherit from :class:`Post`.
|
inherit from :class:`Post`.
|
||||||
|
|
||||||
Comments
|
Comments
|
||||||
@@ -149,7 +148,7 @@ 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 and then query the database again for the comments associated with the
|
||||||
post. This works, but there is no real reason to be storing the comments
|
post. This works, but there is no real reason to be storing the comments
|
||||||
separately from their associated posts, other than to work around the
|
separately from their associated posts, other than to work around the
|
||||||
relational model. Using MongoDB we can store the comments as a list of
|
relational model. Using MongoDB we can store the comments as a list of
|
||||||
@@ -219,8 +218,8 @@ Now that we've got our user in the database, let's add a couple of posts::
|
|||||||
post2.tags = ['mongoengine']
|
post2.tags = ['mongoengine']
|
||||||
post2.save()
|
post2.save()
|
||||||
|
|
||||||
.. note:: If you change a field on a object that has already been saved, then
|
.. note:: If you change a field on an object that has already been saved and
|
||||||
call :meth:`save` again, the document will be updated.
|
then call :meth:`save` again, the document will be updated.
|
||||||
|
|
||||||
Accessing our data
|
Accessing our data
|
||||||
==================
|
==================
|
||||||
@@ -232,17 +231,17 @@ 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::
|
||||||
|
|
||||||
for post in Post.objects:
|
for post in Post.objects:
|
||||||
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`::
|
||||||
|
|
||||||
for post in TextPost.objects:
|
for post in TextPost.objects:
|
||||||
print post.content
|
print(post.content)
|
||||||
|
|
||||||
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:
|
||||||
@@ -259,16 +258,14 @@ instances of :class:`Post` --- they were instances of the subclass of
|
|||||||
practice::
|
practice::
|
||||||
|
|
||||||
for post in Post.objects:
|
for post in Post.objects:
|
||||||
print post.title
|
print(post.title)
|
||||||
print '=' * len(post.title)
|
print('=' * len(post.title))
|
||||||
|
|
||||||
if isinstance(post, TextPost):
|
if isinstance(post, TextPost):
|
||||||
print post.content
|
print(post.content)
|
||||||
|
|
||||||
if isinstance(post, LinkPost):
|
if isinstance(post, LinkPost):
|
||||||
print 'Link:', post.link_url
|
print('Link: {}'.format(post.link_url))
|
||||||
|
|
||||||
print
|
|
||||||
|
|
||||||
This would print the title of each post, followed by the content if it was a
|
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.
|
||||||
@@ -283,7 +280,7 @@ your query. Let's adjust our query so that only posts with the tag "mongodb"
|
|||||||
are returned::
|
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.QuerySet`
|
There are also methods available on :class:`~mongoengine.queryset.QuerySet`
|
||||||
objects that allow different results to be returned, for example, calling
|
objects that allow different results to be returned, for example, calling
|
||||||
@@ -292,11 +289,11 @@ the first matched by the query you provide. Aggregation functions may also be
|
|||||||
used on :class:`~mongoengine.queryset.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 %d posts with tag "mongodb"' % num_posts
|
print('Found {} posts with tag "mongodb"'.format(num_posts))
|
||||||
|
|
||||||
Learning more about mongoengine
|
Learning more about MongoEngine
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
If you got this far you've made a great start, so well done! The next step on
|
If you got this far you've made a great start, so well done! The next step on
|
||||||
your mongoengine journey is the `full user guide <guide/index.html>`_, where you
|
your MongoEngine journey is the `full user guide <guide/index.html>`_, where
|
||||||
can learn indepth about how to use mongoengine and mongodb.
|
you can learn in-depth about how to use MongoEngine and MongoDB.
|
||||||
|
|||||||
@@ -158,44 +158,49 @@ class BaseQuerySet(object):
|
|||||||
# self._cursor
|
# self._cursor
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
"""Support skip and limit using getitem and slicing syntax."""
|
"""Return a document instance corresponding to a given index if
|
||||||
|
the key is an integer. If the key is a slice, translate its
|
||||||
|
bounds into a skip and a limit, and return a cloned queryset
|
||||||
|
with that skip/limit applied. For example:
|
||||||
|
|
||||||
|
>>> User.objects[0]
|
||||||
|
<User: User object>
|
||||||
|
>>> User.objects[1:3]
|
||||||
|
[<User: User object>, <User: User object>]
|
||||||
|
"""
|
||||||
queryset = self.clone()
|
queryset = self.clone()
|
||||||
|
|
||||||
# Slice provided
|
# Handle a slice
|
||||||
if isinstance(key, slice):
|
if isinstance(key, slice):
|
||||||
try:
|
|
||||||
queryset._cursor_obj = queryset._cursor[key]
|
queryset._cursor_obj = queryset._cursor[key]
|
||||||
queryset._skip, queryset._limit = key.start, key.stop
|
queryset._skip, queryset._limit = key.start, key.stop
|
||||||
if key.start and key.stop:
|
if key.start and key.stop:
|
||||||
queryset._limit = key.stop - key.start
|
queryset._limit = key.stop - key.start
|
||||||
except IndexError as err:
|
|
||||||
# PyMongo raises an error if key.start == key.stop, catch it,
|
|
||||||
# bin it, kill it.
|
|
||||||
start = key.start or 0
|
|
||||||
if start >= 0 and key.stop >= 0 and key.step is None:
|
|
||||||
if start == key.stop:
|
|
||||||
queryset.limit(0)
|
|
||||||
queryset._skip = key.start
|
|
||||||
queryset._limit = key.stop - start
|
|
||||||
return queryset
|
|
||||||
raise err
|
|
||||||
# Allow further QuerySet modifications to be performed
|
# Allow further QuerySet modifications to be performed
|
||||||
return queryset
|
return queryset
|
||||||
# Integer index provided
|
|
||||||
|
# Handle an index
|
||||||
elif isinstance(key, int):
|
elif isinstance(key, int):
|
||||||
if queryset._scalar:
|
if queryset._scalar:
|
||||||
return queryset._get_scalar(
|
return queryset._get_scalar(
|
||||||
queryset._document._from_son(queryset._cursor[key],
|
queryset._document._from_son(
|
||||||
|
queryset._cursor[key],
|
||||||
_auto_dereference=self._auto_dereference,
|
_auto_dereference=self._auto_dereference,
|
||||||
only_fields=self.only_fields))
|
only_fields=self.only_fields
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if queryset._as_pymongo:
|
if queryset._as_pymongo:
|
||||||
return queryset._get_as_pymongo(queryset._cursor[key])
|
return queryset._get_as_pymongo(queryset._cursor[key])
|
||||||
return queryset._document._from_son(queryset._cursor[key],
|
|
||||||
_auto_dereference=self._auto_dereference,
|
|
||||||
only_fields=self.only_fields)
|
|
||||||
|
|
||||||
raise AttributeError
|
return queryset._document._from_son(
|
||||||
|
queryset._cursor[key],
|
||||||
|
_auto_dereference=self._auto_dereference,
|
||||||
|
only_fields=self.only_fields
|
||||||
|
)
|
||||||
|
|
||||||
|
raise AttributeError('Provide a slice or an integer index')
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@@ -286,7 +291,7 @@ class BaseQuerySet(object):
|
|||||||
|
|
||||||
.. versionadded:: 0.4
|
.. versionadded:: 0.4
|
||||||
"""
|
"""
|
||||||
return self._document(**kwargs).save()
|
return self._document(**kwargs).save(force_insert=True)
|
||||||
|
|
||||||
def first(self):
|
def first(self):
|
||||||
"""Retrieve the first object matching the query."""
|
"""Retrieve the first object matching the query."""
|
||||||
|
|||||||
@@ -412,7 +412,6 @@ class IndexesTest(unittest.TestCase):
|
|||||||
User.ensure_indexes()
|
User.ensure_indexes()
|
||||||
info = User.objects._collection.index_information()
|
info = User.objects._collection.index_information()
|
||||||
self.assertEqual(sorted(info.keys()), ['_cls_1_user_guid_1', '_id_'])
|
self.assertEqual(sorted(info.keys()), ['_cls_1_user_guid_1', '_id_'])
|
||||||
User.drop_collection()
|
|
||||||
|
|
||||||
def test_embedded_document_index(self):
|
def test_embedded_document_index(self):
|
||||||
"""Tests settings an index on an embedded document
|
"""Tests settings an index on an embedded document
|
||||||
@@ -434,7 +433,6 @@ class IndexesTest(unittest.TestCase):
|
|||||||
|
|
||||||
info = BlogPost.objects._collection.index_information()
|
info = BlogPost.objects._collection.index_information()
|
||||||
self.assertEqual(sorted(info.keys()), ['_id_', 'date.yr_-1'])
|
self.assertEqual(sorted(info.keys()), ['_id_', 'date.yr_-1'])
|
||||||
BlogPost.drop_collection()
|
|
||||||
|
|
||||||
def test_list_embedded_document_index(self):
|
def test_list_embedded_document_index(self):
|
||||||
"""Ensure list embedded documents can be indexed
|
"""Ensure list embedded documents can be indexed
|
||||||
@@ -461,7 +459,6 @@ class IndexesTest(unittest.TestCase):
|
|||||||
post1 = BlogPost(title="Embedded Indexes tests in place",
|
post1 = BlogPost(title="Embedded Indexes tests in place",
|
||||||
tags=[Tag(name="about"), Tag(name="time")])
|
tags=[Tag(name="about"), Tag(name="time")])
|
||||||
post1.save()
|
post1.save()
|
||||||
BlogPost.drop_collection()
|
|
||||||
|
|
||||||
def test_recursive_embedded_objects_dont_break_indexes(self):
|
def test_recursive_embedded_objects_dont_break_indexes(self):
|
||||||
|
|
||||||
@@ -622,8 +619,6 @@ class IndexesTest(unittest.TestCase):
|
|||||||
post3 = BlogPost(title='test3', date=Date(year=2010), slug='test')
|
post3 = BlogPost(title='test3', date=Date(year=2010), slug='test')
|
||||||
self.assertRaises(OperationError, post3.save)
|
self.assertRaises(OperationError, post3.save)
|
||||||
|
|
||||||
BlogPost.drop_collection()
|
|
||||||
|
|
||||||
def test_unique_embedded_document(self):
|
def test_unique_embedded_document(self):
|
||||||
"""Ensure that uniqueness constraints are applied to fields on embedded documents.
|
"""Ensure that uniqueness constraints are applied to fields on embedded documents.
|
||||||
"""
|
"""
|
||||||
@@ -651,8 +646,6 @@ class IndexesTest(unittest.TestCase):
|
|||||||
sub=SubDocument(year=2010, slug='test'))
|
sub=SubDocument(year=2010, slug='test'))
|
||||||
self.assertRaises(NotUniqueError, post3.save)
|
self.assertRaises(NotUniqueError, post3.save)
|
||||||
|
|
||||||
BlogPost.drop_collection()
|
|
||||||
|
|
||||||
def test_unique_embedded_document_in_list(self):
|
def test_unique_embedded_document_in_list(self):
|
||||||
"""
|
"""
|
||||||
Ensure that the uniqueness constraints are applied to fields in
|
Ensure that the uniqueness constraints are applied to fields in
|
||||||
@@ -683,8 +676,6 @@ class IndexesTest(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(NotUniqueError, post2.save)
|
self.assertRaises(NotUniqueError, post2.save)
|
||||||
|
|
||||||
BlogPost.drop_collection()
|
|
||||||
|
|
||||||
def test_unique_with_embedded_document_and_embedded_unique(self):
|
def test_unique_with_embedded_document_and_embedded_unique(self):
|
||||||
"""Ensure that uniqueness constraints are applied to fields on
|
"""Ensure that uniqueness constraints are applied to fields on
|
||||||
embedded documents. And work with unique_with as well.
|
embedded documents. And work with unique_with as well.
|
||||||
@@ -718,8 +709,6 @@ class IndexesTest(unittest.TestCase):
|
|||||||
sub=SubDocument(year=2009, slug='test-1'))
|
sub=SubDocument(year=2009, slug='test-1'))
|
||||||
self.assertRaises(NotUniqueError, post3.save)
|
self.assertRaises(NotUniqueError, post3.save)
|
||||||
|
|
||||||
BlogPost.drop_collection()
|
|
||||||
|
|
||||||
def test_ttl_indexes(self):
|
def test_ttl_indexes(self):
|
||||||
|
|
||||||
class Log(Document):
|
class Log(Document):
|
||||||
@@ -759,13 +748,11 @@ class IndexesTest(unittest.TestCase):
|
|||||||
raise AssertionError("We saved a dupe!")
|
raise AssertionError("We saved a dupe!")
|
||||||
except NotUniqueError:
|
except NotUniqueError:
|
||||||
pass
|
pass
|
||||||
Customer.drop_collection()
|
|
||||||
|
|
||||||
def test_unique_and_primary(self):
|
def test_unique_and_primary(self):
|
||||||
"""If you set a field as primary, then unexpected behaviour can occur.
|
"""If you set a field as primary, then unexpected behaviour can occur.
|
||||||
You won't create a duplicate but you will update an existing document.
|
You won't create a duplicate but you will update an existing document.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class User(Document):
|
class User(Document):
|
||||||
name = StringField(primary_key=True, unique=True)
|
name = StringField(primary_key=True, unique=True)
|
||||||
password = StringField()
|
password = StringField()
|
||||||
@@ -781,8 +768,23 @@ class IndexesTest(unittest.TestCase):
|
|||||||
self.assertEqual(User.objects.count(), 1)
|
self.assertEqual(User.objects.count(), 1)
|
||||||
self.assertEqual(User.objects.get().password, 'secret2')
|
self.assertEqual(User.objects.get().password, 'secret2')
|
||||||
|
|
||||||
|
def test_unique_and_primary_create(self):
|
||||||
|
"""Create a new record with a duplicate primary key
|
||||||
|
throws an exception
|
||||||
|
"""
|
||||||
|
class User(Document):
|
||||||
|
name = StringField(primary_key=True)
|
||||||
|
password = StringField()
|
||||||
|
|
||||||
User.drop_collection()
|
User.drop_collection()
|
||||||
|
|
||||||
|
User.objects.create(name='huangz', password='secret')
|
||||||
|
with self.assertRaises(NotUniqueError):
|
||||||
|
User.objects.create(name='huangz', password='secret2')
|
||||||
|
|
||||||
|
self.assertEqual(User.objects.count(), 1)
|
||||||
|
self.assertEqual(User.objects.get().password, 'secret')
|
||||||
|
|
||||||
def test_index_with_pk(self):
|
def test_index_with_pk(self):
|
||||||
"""Ensure you can use `pk` as part of a query"""
|
"""Ensure you can use `pk` as part of a query"""
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ TEST_IMAGE_PATH = os.path.join(os.path.dirname(__file__),
|
|||||||
__all__ = ("InstanceTest",)
|
__all__ = ("InstanceTest",)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class InstanceTest(unittest.TestCase):
|
class InstanceTest(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -72,8 +70,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(field._instance, instance)
|
self.assertEqual(field._instance, instance)
|
||||||
|
|
||||||
def test_capped_collection(self):
|
def test_capped_collection(self):
|
||||||
"""Ensure that capped collections work properly.
|
"""Ensure that capped collections work properly."""
|
||||||
"""
|
|
||||||
class Log(Document):
|
class Log(Document):
|
||||||
date = DateTimeField(default=datetime.now)
|
date = DateTimeField(default=datetime.now)
|
||||||
meta = {
|
meta = {
|
||||||
@@ -181,8 +178,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual('<Article: привет мир>', repr(doc))
|
self.assertEqual('<Article: привет мир>', repr(doc))
|
||||||
|
|
||||||
def test_repr_none(self):
|
def test_repr_none(self):
|
||||||
"""Ensure None values handled correctly
|
"""Ensure None values are handled correctly."""
|
||||||
"""
|
|
||||||
class Article(Document):
|
class Article(Document):
|
||||||
title = StringField()
|
title = StringField()
|
||||||
|
|
||||||
@@ -190,25 +186,23 @@ class InstanceTest(unittest.TestCase):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
doc = Article(title=u'привет мир')
|
doc = Article(title=u'привет мир')
|
||||||
|
|
||||||
self.assertEqual('<Article: None>', repr(doc))
|
self.assertEqual('<Article: None>', repr(doc))
|
||||||
|
|
||||||
def test_queryset_resurrects_dropped_collection(self):
|
def test_queryset_resurrects_dropped_collection(self):
|
||||||
self.Person.drop_collection()
|
self.Person.drop_collection()
|
||||||
|
|
||||||
self.assertEqual([], list(self.Person.objects()))
|
self.assertEqual([], list(self.Person.objects()))
|
||||||
|
|
||||||
|
# Ensure works correctly with inhertited classes
|
||||||
class Actor(self.Person):
|
class Actor(self.Person):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Ensure works correctly with inhertited classes
|
|
||||||
Actor.objects()
|
Actor.objects()
|
||||||
self.Person.drop_collection()
|
self.Person.drop_collection()
|
||||||
self.assertEqual([], list(Actor.objects()))
|
self.assertEqual([], list(Actor.objects()))
|
||||||
|
|
||||||
def test_polymorphic_references(self):
|
def test_polymorphic_references(self):
|
||||||
"""Ensure that the correct subclasses are returned from a query when
|
"""Ensure that the correct subclasses are returned from a query
|
||||||
using references / generic references
|
when using references / generic references
|
||||||
"""
|
"""
|
||||||
class Animal(Document):
|
class Animal(Document):
|
||||||
meta = {'allow_inheritance': True}
|
meta = {'allow_inheritance': True}
|
||||||
@@ -258,9 +252,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
classes = [a.__class__ for a in Zoo.objects.first().animals]
|
classes = [a.__class__ for a in Zoo.objects.first().animals]
|
||||||
self.assertEqual(classes, [Animal, Fish, Mammal, Dog, Human])
|
self.assertEqual(classes, [Animal, Fish, Mammal, Dog, Human])
|
||||||
|
|
||||||
Zoo.drop_collection()
|
|
||||||
Animal.drop_collection()
|
|
||||||
|
|
||||||
def test_reference_inheritance(self):
|
def test_reference_inheritance(self):
|
||||||
class Stats(Document):
|
class Stats(Document):
|
||||||
created = DateTimeField(default=datetime.now)
|
created = DateTimeField(default=datetime.now)
|
||||||
@@ -287,8 +278,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(list_stats, CompareStats.objects.first().stats)
|
self.assertEqual(list_stats, CompareStats.objects.first().stats)
|
||||||
|
|
||||||
def test_db_field_load(self):
|
def test_db_field_load(self):
|
||||||
"""Ensure we load data correctly
|
"""Ensure we load data correctly from the right db field."""
|
||||||
"""
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
name = StringField(required=True)
|
name = StringField(required=True)
|
||||||
_rank = StringField(required=False, db_field="rank")
|
_rank = StringField(required=False, db_field="rank")
|
||||||
@@ -307,8 +297,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(Person.objects.get(name="Fred").rank, "Private")
|
self.assertEqual(Person.objects.get(name="Fred").rank, "Private")
|
||||||
|
|
||||||
def test_db_embedded_doc_field_load(self):
|
def test_db_embedded_doc_field_load(self):
|
||||||
"""Ensure we load embedded document data correctly
|
"""Ensure we load embedded document data correctly."""
|
||||||
"""
|
|
||||||
class Rank(EmbeddedDocument):
|
class Rank(EmbeddedDocument):
|
||||||
title = StringField(required=True)
|
title = StringField(required=True)
|
||||||
|
|
||||||
@@ -333,8 +322,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(Person.objects.get(name="Fred").rank, "Private")
|
self.assertEqual(Person.objects.get(name="Fred").rank, "Private")
|
||||||
|
|
||||||
def test_custom_id_field(self):
|
def test_custom_id_field(self):
|
||||||
"""Ensure that documents may be created with custom primary keys.
|
"""Ensure that documents may be created with custom primary keys."""
|
||||||
"""
|
|
||||||
class User(Document):
|
class User(Document):
|
||||||
username = StringField(primary_key=True)
|
username = StringField(primary_key=True)
|
||||||
name = StringField()
|
name = StringField()
|
||||||
@@ -382,10 +370,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(user_son['_id'], 'mongo')
|
self.assertEqual(user_son['_id'], 'mongo')
|
||||||
self.assertTrue('username' not in user_son['_id'])
|
self.assertTrue('username' not in user_son['_id'])
|
||||||
|
|
||||||
User.drop_collection()
|
|
||||||
|
|
||||||
def test_document_not_registered(self):
|
def test_document_not_registered(self):
|
||||||
|
|
||||||
class Place(Document):
|
class Place(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
@@ -407,7 +392,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
list(Place.objects.all())
|
list(Place.objects.all())
|
||||||
|
|
||||||
def test_document_registry_regressions(self):
|
def test_document_registry_regressions(self):
|
||||||
|
|
||||||
class Location(Document):
|
class Location(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
meta = {'allow_inheritance': True}
|
meta = {'allow_inheritance': True}
|
||||||
@@ -421,18 +405,16 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(Area, get_document("Location.Area"))
|
self.assertEqual(Area, get_document("Location.Area"))
|
||||||
|
|
||||||
def test_creation(self):
|
def test_creation(self):
|
||||||
"""Ensure that document may be created using keyword arguments.
|
"""Ensure that document may be created using keyword arguments."""
|
||||||
"""
|
|
||||||
person = self.Person(name="Test User", age=30)
|
person = self.Person(name="Test User", age=30)
|
||||||
self.assertEqual(person.name, "Test User")
|
self.assertEqual(person.name, "Test User")
|
||||||
self.assertEqual(person.age, 30)
|
self.assertEqual(person.age, 30)
|
||||||
|
|
||||||
def test_to_dbref(self):
|
def test_to_dbref(self):
|
||||||
"""Ensure that you can get a dbref of a document"""
|
"""Ensure that you can get a dbref of a document."""
|
||||||
person = self.Person(name="Test User", age=30)
|
person = self.Person(name="Test User", age=30)
|
||||||
self.assertRaises(OperationError, person.to_dbref)
|
self.assertRaises(OperationError, person.to_dbref)
|
||||||
person.save()
|
person.save()
|
||||||
|
|
||||||
person.to_dbref()
|
person.to_dbref()
|
||||||
|
|
||||||
def test_save_abstract_document(self):
|
def test_save_abstract_document(self):
|
||||||
@@ -445,8 +427,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
Doc(name='aaa').save()
|
Doc(name='aaa').save()
|
||||||
|
|
||||||
def test_reload(self):
|
def test_reload(self):
|
||||||
"""Ensure that attributes may be reloaded.
|
"""Ensure that attributes may be reloaded."""
|
||||||
"""
|
|
||||||
person = self.Person(name="Test User", age=20)
|
person = self.Person(name="Test User", age=20)
|
||||||
person.save()
|
person.save()
|
||||||
|
|
||||||
@@ -479,7 +460,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
doc = Animal(superphylum='Deuterostomia')
|
doc = Animal(superphylum='Deuterostomia')
|
||||||
doc.save()
|
doc.save()
|
||||||
doc.reload()
|
doc.reload()
|
||||||
Animal.drop_collection()
|
|
||||||
|
|
||||||
def test_reload_sharded_nested(self):
|
def test_reload_sharded_nested(self):
|
||||||
class SuperPhylum(EmbeddedDocument):
|
class SuperPhylum(EmbeddedDocument):
|
||||||
@@ -493,11 +473,9 @@ class InstanceTest(unittest.TestCase):
|
|||||||
doc = Animal(superphylum=SuperPhylum(name='Deuterostomia'))
|
doc = Animal(superphylum=SuperPhylum(name='Deuterostomia'))
|
||||||
doc.save()
|
doc.save()
|
||||||
doc.reload()
|
doc.reload()
|
||||||
Animal.drop_collection()
|
|
||||||
|
|
||||||
def test_reload_referencing(self):
|
def test_reload_referencing(self):
|
||||||
"""Ensures reloading updates weakrefs correctly
|
"""Ensures reloading updates weakrefs correctly."""
|
||||||
"""
|
|
||||||
class Embedded(EmbeddedDocument):
|
class Embedded(EmbeddedDocument):
|
||||||
dict_field = DictField()
|
dict_field = DictField()
|
||||||
list_field = ListField()
|
list_field = ListField()
|
||||||
@@ -569,8 +547,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertFalse("Threw wrong exception")
|
self.assertFalse("Threw wrong exception")
|
||||||
|
|
||||||
def test_reload_of_non_strict_with_special_field_name(self):
|
def test_reload_of_non_strict_with_special_field_name(self):
|
||||||
"""Ensures reloading works for documents with meta strict == False
|
"""Ensures reloading works for documents with meta strict == False."""
|
||||||
"""
|
|
||||||
class Post(Document):
|
class Post(Document):
|
||||||
meta = {
|
meta = {
|
||||||
'strict': False
|
'strict': False
|
||||||
@@ -591,8 +568,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(post.items, ["more lorem", "even more ipsum"])
|
self.assertEqual(post.items, ["more lorem", "even more ipsum"])
|
||||||
|
|
||||||
def test_dictionary_access(self):
|
def test_dictionary_access(self):
|
||||||
"""Ensure that dictionary-style field access works properly.
|
"""Ensure that dictionary-style field access works properly."""
|
||||||
"""
|
|
||||||
person = self.Person(name='Test User', age=30, job=self.Job())
|
person = self.Person(name='Test User', age=30, job=self.Job())
|
||||||
self.assertEqual(person['name'], 'Test User')
|
self.assertEqual(person['name'], 'Test User')
|
||||||
|
|
||||||
@@ -634,8 +610,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(sub_doc.to_mongo().keys(), ['id'])
|
self.assertEqual(sub_doc.to_mongo().keys(), ['id'])
|
||||||
|
|
||||||
def test_embedded_document(self):
|
def test_embedded_document(self):
|
||||||
"""Ensure that embedded documents are set up correctly.
|
"""Ensure that embedded documents are set up correctly."""
|
||||||
"""
|
|
||||||
class Comment(EmbeddedDocument):
|
class Comment(EmbeddedDocument):
|
||||||
content = StringField()
|
content = StringField()
|
||||||
|
|
||||||
@@ -643,8 +618,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertFalse('id' in Comment._fields)
|
self.assertFalse('id' in Comment._fields)
|
||||||
|
|
||||||
def test_embedded_document_instance(self):
|
def test_embedded_document_instance(self):
|
||||||
"""Ensure that embedded documents can reference parent instance
|
"""Ensure that embedded documents can reference parent instance."""
|
||||||
"""
|
|
||||||
class Embedded(EmbeddedDocument):
|
class Embedded(EmbeddedDocument):
|
||||||
string = StringField()
|
string = StringField()
|
||||||
|
|
||||||
@@ -652,6 +626,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
embedded_field = EmbeddedDocumentField(Embedded)
|
embedded_field = EmbeddedDocumentField(Embedded)
|
||||||
|
|
||||||
Doc.drop_collection()
|
Doc.drop_collection()
|
||||||
|
|
||||||
doc = Doc(embedded_field=Embedded(string="Hi"))
|
doc = Doc(embedded_field=Embedded(string="Hi"))
|
||||||
self.assertHasInstance(doc.embedded_field, doc)
|
self.assertHasInstance(doc.embedded_field, doc)
|
||||||
|
|
||||||
@@ -661,7 +636,8 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_embedded_document_complex_instance(self):
|
def test_embedded_document_complex_instance(self):
|
||||||
"""Ensure that embedded documents in complex fields can reference
|
"""Ensure that embedded documents in complex fields can reference
|
||||||
parent instance"""
|
parent instance.
|
||||||
|
"""
|
||||||
class Embedded(EmbeddedDocument):
|
class Embedded(EmbeddedDocument):
|
||||||
string = StringField()
|
string = StringField()
|
||||||
|
|
||||||
@@ -677,8 +653,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertHasInstance(doc.embedded_field[0], doc)
|
self.assertHasInstance(doc.embedded_field[0], doc)
|
||||||
|
|
||||||
def test_embedded_document_complex_instance_no_use_db_field(self):
|
def test_embedded_document_complex_instance_no_use_db_field(self):
|
||||||
"""Ensure that use_db_field is propagated to list of Emb Docs
|
"""Ensure that use_db_field is propagated to list of Emb Docs."""
|
||||||
"""
|
|
||||||
class Embedded(EmbeddedDocument):
|
class Embedded(EmbeddedDocument):
|
||||||
string = StringField(db_field='s')
|
string = StringField(db_field='s')
|
||||||
|
|
||||||
@@ -690,7 +665,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(d['embedded_field'], [{'string': 'Hi'}])
|
self.assertEqual(d['embedded_field'], [{'string': 'Hi'}])
|
||||||
|
|
||||||
def test_instance_is_set_on_setattr(self):
|
def test_instance_is_set_on_setattr(self):
|
||||||
|
|
||||||
class Email(EmbeddedDocument):
|
class Email(EmbeddedDocument):
|
||||||
email = EmailField()
|
email = EmailField()
|
||||||
|
|
||||||
@@ -698,6 +672,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
email = EmbeddedDocumentField(Email)
|
email = EmbeddedDocumentField(Email)
|
||||||
|
|
||||||
Account.drop_collection()
|
Account.drop_collection()
|
||||||
|
|
||||||
acc = Account()
|
acc = Account()
|
||||||
acc.email = Email(email='test@example.com')
|
acc.email = Email(email='test@example.com')
|
||||||
self.assertHasInstance(acc._data["email"], acc)
|
self.assertHasInstance(acc._data["email"], acc)
|
||||||
@@ -707,7 +682,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertHasInstance(acc1._data["email"], acc1)
|
self.assertHasInstance(acc1._data["email"], acc1)
|
||||||
|
|
||||||
def test_instance_is_set_on_setattr_on_embedded_document_list(self):
|
def test_instance_is_set_on_setattr_on_embedded_document_list(self):
|
||||||
|
|
||||||
class Email(EmbeddedDocument):
|
class Email(EmbeddedDocument):
|
||||||
email = EmailField()
|
email = EmailField()
|
||||||
|
|
||||||
@@ -853,32 +827,28 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertDbEqual([dict(other_doc.to_mongo()), dict(doc.to_mongo())])
|
self.assertDbEqual([dict(other_doc.to_mongo()), dict(doc.to_mongo())])
|
||||||
|
|
||||||
def test_save(self):
|
def test_save(self):
|
||||||
"""Ensure that a document may be saved in the database.
|
"""Ensure that a document may be saved in the database."""
|
||||||
"""
|
|
||||||
# Create person object and save it to the database
|
# Create person object and save it to the database
|
||||||
person = self.Person(name='Test User', age=30)
|
person = self.Person(name='Test User', age=30)
|
||||||
person.save()
|
person.save()
|
||||||
|
|
||||||
# Ensure that the object is in the database
|
# Ensure that the object is in the database
|
||||||
collection = self.db[self.Person._get_collection_name()]
|
collection = self.db[self.Person._get_collection_name()]
|
||||||
person_obj = collection.find_one({'name': 'Test User'})
|
person_obj = collection.find_one({'name': 'Test User'})
|
||||||
self.assertEqual(person_obj['name'], 'Test User')
|
self.assertEqual(person_obj['name'], 'Test User')
|
||||||
self.assertEqual(person_obj['age'], 30)
|
self.assertEqual(person_obj['age'], 30)
|
||||||
self.assertEqual(person_obj['_id'], person.id)
|
self.assertEqual(person_obj['_id'], person.id)
|
||||||
# Test skipping validation on save
|
|
||||||
|
|
||||||
|
# Test skipping validation on save
|
||||||
class Recipient(Document):
|
class Recipient(Document):
|
||||||
email = EmailField(required=True)
|
email = EmailField(required=True)
|
||||||
|
|
||||||
recipient = Recipient(email='root@localhost')
|
recipient = Recipient(email='root@localhost')
|
||||||
self.assertRaises(ValidationError, recipient.save)
|
self.assertRaises(ValidationError, recipient.save)
|
||||||
|
|
||||||
try:
|
|
||||||
recipient.save(validate=False)
|
recipient.save(validate=False)
|
||||||
except ValidationError:
|
|
||||||
self.fail()
|
|
||||||
|
|
||||||
def test_save_to_a_value_that_equates_to_false(self):
|
def test_save_to_a_value_that_equates_to_false(self):
|
||||||
|
|
||||||
class Thing(EmbeddedDocument):
|
class Thing(EmbeddedDocument):
|
||||||
count = IntField()
|
count = IntField()
|
||||||
|
|
||||||
@@ -898,7 +868,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(user.thing.count, 0)
|
self.assertEqual(user.thing.count, 0)
|
||||||
|
|
||||||
def test_save_max_recursion_not_hit(self):
|
def test_save_max_recursion_not_hit(self):
|
||||||
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
parent = ReferenceField('self')
|
parent = ReferenceField('self')
|
||||||
@@ -924,7 +893,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
p0.save()
|
p0.save()
|
||||||
|
|
||||||
def test_save_max_recursion_not_hit_with_file_field(self):
|
def test_save_max_recursion_not_hit_with_file_field(self):
|
||||||
|
|
||||||
class Foo(Document):
|
class Foo(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
picture = FileField()
|
picture = FileField()
|
||||||
@@ -948,7 +916,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(b.picture, b.bar.picture, b.bar.bar.picture)
|
self.assertEqual(b.picture, b.bar.picture, b.bar.bar.picture)
|
||||||
|
|
||||||
def test_save_cascades(self):
|
def test_save_cascades(self):
|
||||||
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
parent = ReferenceField('self')
|
parent = ReferenceField('self')
|
||||||
@@ -971,7 +938,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(p1.name, p.parent.name)
|
self.assertEqual(p1.name, p.parent.name)
|
||||||
|
|
||||||
def test_save_cascade_kwargs(self):
|
def test_save_cascade_kwargs(self):
|
||||||
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
parent = ReferenceField('self')
|
parent = ReferenceField('self')
|
||||||
@@ -992,7 +958,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(p1.name, p2.parent.name)
|
self.assertEqual(p1.name, p2.parent.name)
|
||||||
|
|
||||||
def test_save_cascade_meta_false(self):
|
def test_save_cascade_meta_false(self):
|
||||||
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
parent = ReferenceField('self')
|
parent = ReferenceField('self')
|
||||||
@@ -1021,7 +986,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(p1.name, p.parent.name)
|
self.assertEqual(p1.name, p.parent.name)
|
||||||
|
|
||||||
def test_save_cascade_meta_true(self):
|
def test_save_cascade_meta_true(self):
|
||||||
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
parent = ReferenceField('self')
|
parent = ReferenceField('self')
|
||||||
@@ -1046,7 +1010,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertNotEqual(p1.name, p.parent.name)
|
self.assertNotEqual(p1.name, p.parent.name)
|
||||||
|
|
||||||
def test_save_cascades_generically(self):
|
def test_save_cascades_generically(self):
|
||||||
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
parent = GenericReferenceField()
|
parent = GenericReferenceField()
|
||||||
@@ -1072,7 +1035,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(p1.name, p.parent.name)
|
self.assertEqual(p1.name, p.parent.name)
|
||||||
|
|
||||||
def test_save_atomicity_condition(self):
|
def test_save_atomicity_condition(self):
|
||||||
|
|
||||||
class Widget(Document):
|
class Widget(Document):
|
||||||
toggle = BooleanField(default=False)
|
toggle = BooleanField(default=False)
|
||||||
count = IntField(default=0)
|
count = IntField(default=0)
|
||||||
@@ -1150,7 +1112,8 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_update(self):
|
def test_update(self):
|
||||||
"""Ensure that an existing document is updated instead of be
|
"""Ensure that an existing document is updated instead of be
|
||||||
overwritten."""
|
overwritten.
|
||||||
|
"""
|
||||||
# Create person object and save it to the database
|
# Create person object and save it to the database
|
||||||
person = self.Person(name='Test User', age=30)
|
person = self.Person(name='Test User', age=30)
|
||||||
person.save()
|
person.save()
|
||||||
@@ -1254,7 +1217,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(2, self.Person.objects.count())
|
self.assertEqual(2, self.Person.objects.count())
|
||||||
|
|
||||||
def test_can_save_if_not_included(self):
|
def test_can_save_if_not_included(self):
|
||||||
|
|
||||||
class EmbeddedDoc(EmbeddedDocument):
|
class EmbeddedDoc(EmbeddedDocument):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1341,10 +1303,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
doc2.update(set__name=doc1.name)
|
doc2.update(set__name=doc1.name)
|
||||||
|
|
||||||
def test_embedded_update(self):
|
def test_embedded_update(self):
|
||||||
"""
|
"""Test update on `EmbeddedDocumentField` fields."""
|
||||||
Test update on `EmbeddedDocumentField` fields
|
|
||||||
"""
|
|
||||||
|
|
||||||
class Page(EmbeddedDocument):
|
class Page(EmbeddedDocument):
|
||||||
log_message = StringField(verbose_name="Log message",
|
log_message = StringField(verbose_name="Log message",
|
||||||
required=True)
|
required=True)
|
||||||
@@ -1365,11 +1324,9 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(site.page.log_message, "Error: Dummy message")
|
self.assertEqual(site.page.log_message, "Error: Dummy message")
|
||||||
|
|
||||||
def test_embedded_update_db_field(self):
|
def test_embedded_update_db_field(self):
|
||||||
|
"""Test update on `EmbeddedDocumentField` fields when db_field
|
||||||
|
is other than default.
|
||||||
"""
|
"""
|
||||||
Test update on `EmbeddedDocumentField` fields when db_field is other
|
|
||||||
than default.
|
|
||||||
"""
|
|
||||||
|
|
||||||
class Page(EmbeddedDocument):
|
class Page(EmbeddedDocument):
|
||||||
log_message = StringField(verbose_name="Log message",
|
log_message = StringField(verbose_name="Log message",
|
||||||
db_field="page_log_message",
|
db_field="page_log_message",
|
||||||
@@ -1392,9 +1349,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(site.page.log_message, "Error: Dummy message")
|
self.assertEqual(site.page.log_message, "Error: Dummy message")
|
||||||
|
|
||||||
def test_save_only_changed_fields(self):
|
def test_save_only_changed_fields(self):
|
||||||
"""Ensure save only sets / unsets changed fields
|
"""Ensure save only sets / unsets changed fields."""
|
||||||
"""
|
|
||||||
|
|
||||||
class User(self.Person):
|
class User(self.Person):
|
||||||
active = BooleanField(default=True)
|
active = BooleanField(default=True)
|
||||||
|
|
||||||
@@ -1514,8 +1469,8 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(q, 3)
|
self.assertEqual(q, 3)
|
||||||
|
|
||||||
def test_set_unset_one_operation(self):
|
def test_set_unset_one_operation(self):
|
||||||
"""Ensure that $set and $unset actions are performed in the same
|
"""Ensure that $set and $unset actions are performed in the
|
||||||
operation.
|
same operation.
|
||||||
"""
|
"""
|
||||||
class FooBar(Document):
|
class FooBar(Document):
|
||||||
foo = StringField(default=None)
|
foo = StringField(default=None)
|
||||||
@@ -1536,9 +1491,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(1, q)
|
self.assertEqual(1, q)
|
||||||
|
|
||||||
def test_save_only_changed_fields_recursive(self):
|
def test_save_only_changed_fields_recursive(self):
|
||||||
"""Ensure save only sets / unsets changed fields
|
"""Ensure save only sets / unsets changed fields."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Comment(EmbeddedDocument):
|
class Comment(EmbeddedDocument):
|
||||||
published = BooleanField(default=True)
|
published = BooleanField(default=True)
|
||||||
|
|
||||||
@@ -1578,8 +1531,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertFalse(person.comments_dict['first_post'].published)
|
self.assertFalse(person.comments_dict['first_post'].published)
|
||||||
|
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
"""Ensure that document may be deleted using the delete method.
|
"""Ensure that document may be deleted using the delete method."""
|
||||||
"""
|
|
||||||
person = self.Person(name="Test User", age=30)
|
person = self.Person(name="Test User", age=30)
|
||||||
person.save()
|
person.save()
|
||||||
self.assertEqual(self.Person.objects.count(), 1)
|
self.assertEqual(self.Person.objects.count(), 1)
|
||||||
@@ -1587,33 +1539,34 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(self.Person.objects.count(), 0)
|
self.assertEqual(self.Person.objects.count(), 0)
|
||||||
|
|
||||||
def test_save_custom_id(self):
|
def test_save_custom_id(self):
|
||||||
"""Ensure that a document may be saved with a custom _id.
|
"""Ensure that a document may be saved with a custom _id."""
|
||||||
"""
|
|
||||||
# Create person object and save it to the database
|
# Create person object and save it to the database
|
||||||
person = self.Person(name='Test User', age=30,
|
person = self.Person(name='Test User', age=30,
|
||||||
id='497ce96f395f2f052a494fd4')
|
id='497ce96f395f2f052a494fd4')
|
||||||
person.save()
|
person.save()
|
||||||
|
|
||||||
# Ensure that the object is in the database with the correct _id
|
# Ensure that the object is in the database with the correct _id
|
||||||
collection = self.db[self.Person._get_collection_name()]
|
collection = self.db[self.Person._get_collection_name()]
|
||||||
person_obj = collection.find_one({'name': 'Test User'})
|
person_obj = collection.find_one({'name': 'Test User'})
|
||||||
self.assertEqual(str(person_obj['_id']), '497ce96f395f2f052a494fd4')
|
self.assertEqual(str(person_obj['_id']), '497ce96f395f2f052a494fd4')
|
||||||
|
|
||||||
def test_save_custom_pk(self):
|
def test_save_custom_pk(self):
|
||||||
"""
|
"""Ensure that a document may be saved with a custom _id using
|
||||||
Ensure that a document may be saved with a custom _id using pk alias.
|
pk alias.
|
||||||
"""
|
"""
|
||||||
# Create person object and save it to the database
|
# Create person object and save it to the database
|
||||||
person = self.Person(name='Test User', age=30,
|
person = self.Person(name='Test User', age=30,
|
||||||
pk='497ce96f395f2f052a494fd4')
|
pk='497ce96f395f2f052a494fd4')
|
||||||
person.save()
|
person.save()
|
||||||
|
|
||||||
# Ensure that the object is in the database with the correct _id
|
# Ensure that the object is in the database with the correct _id
|
||||||
collection = self.db[self.Person._get_collection_name()]
|
collection = self.db[self.Person._get_collection_name()]
|
||||||
person_obj = collection.find_one({'name': 'Test User'})
|
person_obj = collection.find_one({'name': 'Test User'})
|
||||||
self.assertEqual(str(person_obj['_id']), '497ce96f395f2f052a494fd4')
|
self.assertEqual(str(person_obj['_id']), '497ce96f395f2f052a494fd4')
|
||||||
|
|
||||||
def test_save_list(self):
|
def test_save_list(self):
|
||||||
"""Ensure that a list field may be properly saved.
|
"""Ensure that a list field may be properly saved."""
|
||||||
"""
|
|
||||||
class Comment(EmbeddedDocument):
|
class Comment(EmbeddedDocument):
|
||||||
content = StringField()
|
content = StringField()
|
||||||
|
|
||||||
@@ -1636,8 +1589,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
for comment_obj, comment in zip(post_obj['comments'], comments):
|
for comment_obj, comment in zip(post_obj['comments'], comments):
|
||||||
self.assertEqual(comment_obj['content'], comment['content'])
|
self.assertEqual(comment_obj['content'], comment['content'])
|
||||||
|
|
||||||
BlogPost.drop_collection()
|
|
||||||
|
|
||||||
def test_list_search_by_embedded(self):
|
def test_list_search_by_embedded(self):
|
||||||
class User(Document):
|
class User(Document):
|
||||||
username = StringField(required=True)
|
username = StringField(required=True)
|
||||||
@@ -1697,8 +1648,8 @@ class InstanceTest(unittest.TestCase):
|
|||||||
list(Page.objects.filter(comments__user=u3)))
|
list(Page.objects.filter(comments__user=u3)))
|
||||||
|
|
||||||
def test_save_embedded_document(self):
|
def test_save_embedded_document(self):
|
||||||
"""Ensure that a document with an embedded document field may be
|
"""Ensure that a document with an embedded document field may
|
||||||
saved in the database.
|
be saved in the database.
|
||||||
"""
|
"""
|
||||||
class EmployeeDetails(EmbeddedDocument):
|
class EmployeeDetails(EmbeddedDocument):
|
||||||
position = StringField()
|
position = StringField()
|
||||||
@@ -1717,13 +1668,13 @@ class InstanceTest(unittest.TestCase):
|
|||||||
employee_obj = collection.find_one({'name': 'Test Employee'})
|
employee_obj = collection.find_one({'name': 'Test Employee'})
|
||||||
self.assertEqual(employee_obj['name'], 'Test Employee')
|
self.assertEqual(employee_obj['name'], 'Test Employee')
|
||||||
self.assertEqual(employee_obj['age'], 50)
|
self.assertEqual(employee_obj['age'], 50)
|
||||||
|
|
||||||
# Ensure that the 'details' embedded object saved correctly
|
# Ensure that the 'details' embedded object saved correctly
|
||||||
self.assertEqual(employee_obj['details']['position'], 'Developer')
|
self.assertEqual(employee_obj['details']['position'], 'Developer')
|
||||||
|
|
||||||
def test_embedded_update_after_save(self):
|
def test_embedded_update_after_save(self):
|
||||||
"""
|
"""Test update of `EmbeddedDocumentField` attached to a newly
|
||||||
Test update of `EmbeddedDocumentField` attached to a newly saved
|
saved document.
|
||||||
document.
|
|
||||||
"""
|
"""
|
||||||
class Page(EmbeddedDocument):
|
class Page(EmbeddedDocument):
|
||||||
log_message = StringField(verbose_name="Log message",
|
log_message = StringField(verbose_name="Log message",
|
||||||
@@ -1744,8 +1695,8 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(site.page.log_message, "Error: Dummy message")
|
self.assertEqual(site.page.log_message, "Error: Dummy message")
|
||||||
|
|
||||||
def test_updating_an_embedded_document(self):
|
def test_updating_an_embedded_document(self):
|
||||||
"""Ensure that a document with an embedded document field may be
|
"""Ensure that a document with an embedded document field may
|
||||||
saved in the database.
|
be saved in the database.
|
||||||
"""
|
"""
|
||||||
class EmployeeDetails(EmbeddedDocument):
|
class EmployeeDetails(EmbeddedDocument):
|
||||||
position = StringField()
|
position = StringField()
|
||||||
@@ -1780,7 +1731,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(promoted_employee.details, None)
|
self.assertEqual(promoted_employee.details, None)
|
||||||
|
|
||||||
def test_object_mixins(self):
|
def test_object_mixins(self):
|
||||||
|
|
||||||
class NameMixin(object):
|
class NameMixin(object):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
@@ -1819,9 +1769,9 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(t.count, 12)
|
self.assertEqual(t.count, 12)
|
||||||
|
|
||||||
def test_save_reference(self):
|
def test_save_reference(self):
|
||||||
"""Ensure that a document reference field may be saved in the database.
|
"""Ensure that a document reference field may be saved in the
|
||||||
|
database.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class BlogPost(Document):
|
class BlogPost(Document):
|
||||||
meta = {'collection': 'blogpost_1'}
|
meta = {'collection': 'blogpost_1'}
|
||||||
content = StringField()
|
content = StringField()
|
||||||
@@ -1852,8 +1802,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
author = list(self.Person.objects(name='Test User'))[-1]
|
author = list(self.Person.objects(name='Test User'))[-1]
|
||||||
self.assertEqual(author.age, 25)
|
self.assertEqual(author.age, 25)
|
||||||
|
|
||||||
BlogPost.drop_collection()
|
|
||||||
|
|
||||||
def test_duplicate_db_fields_raise_invalid_document_error(self):
|
def test_duplicate_db_fields_raise_invalid_document_error(self):
|
||||||
"""Ensure a InvalidDocumentError is thrown if duplicate fields
|
"""Ensure a InvalidDocumentError is thrown if duplicate fields
|
||||||
declare the same db_field.
|
declare the same db_field.
|
||||||
@@ -1864,7 +1812,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
name2 = StringField(db_field='name')
|
name2 = StringField(db_field='name')
|
||||||
|
|
||||||
def test_invalid_son(self):
|
def test_invalid_son(self):
|
||||||
"""Raise an error if loading invalid data"""
|
"""Raise an error if loading invalid data."""
|
||||||
class Occurrence(EmbeddedDocument):
|
class Occurrence(EmbeddedDocument):
|
||||||
number = IntField()
|
number = IntField()
|
||||||
|
|
||||||
@@ -1887,9 +1835,9 @@ class InstanceTest(unittest.TestCase):
|
|||||||
Word._from_son('this is not a valid SON dict')
|
Word._from_son('this is not a valid SON dict')
|
||||||
|
|
||||||
def test_reverse_delete_rule_cascade_and_nullify(self):
|
def test_reverse_delete_rule_cascade_and_nullify(self):
|
||||||
"""Ensure that a referenced document is also deleted upon deletion.
|
"""Ensure that a referenced document is also deleted upon
|
||||||
|
deletion.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class BlogPost(Document):
|
class BlogPost(Document):
|
||||||
content = StringField()
|
content = StringField()
|
||||||
author = ReferenceField(self.Person, reverse_delete_rule=CASCADE)
|
author = ReferenceField(self.Person, reverse_delete_rule=CASCADE)
|
||||||
@@ -1944,7 +1892,8 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(Book.objects.count(), 0)
|
self.assertEqual(Book.objects.count(), 0)
|
||||||
|
|
||||||
def test_reverse_delete_rule_with_shared_id_among_collections(self):
|
def test_reverse_delete_rule_with_shared_id_among_collections(self):
|
||||||
"""Ensure that cascade delete rule doesn't mix id among collections.
|
"""Ensure that cascade delete rule doesn't mix id among
|
||||||
|
collections.
|
||||||
"""
|
"""
|
||||||
class User(Document):
|
class User(Document):
|
||||||
id = IntField(primary_key=True)
|
id = IntField(primary_key=True)
|
||||||
@@ -1975,10 +1924,9 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(Book.objects.get(), book_2)
|
self.assertEqual(Book.objects.get(), book_2)
|
||||||
|
|
||||||
def test_reverse_delete_rule_with_document_inheritance(self):
|
def test_reverse_delete_rule_with_document_inheritance(self):
|
||||||
"""Ensure that a referenced document is also deleted upon deletion
|
"""Ensure that a referenced document is also deleted upon
|
||||||
of a child document.
|
deletion of a child document.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Writer(self.Person):
|
class Writer(self.Person):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -2010,10 +1958,9 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(BlogPost.objects.count(), 0)
|
self.assertEqual(BlogPost.objects.count(), 0)
|
||||||
|
|
||||||
def test_reverse_delete_rule_cascade_and_nullify_complex_field(self):
|
def test_reverse_delete_rule_cascade_and_nullify_complex_field(self):
|
||||||
"""Ensure that a referenced document is also deleted upon deletion for
|
"""Ensure that a referenced document is also deleted upon
|
||||||
complex fields.
|
deletion for complex fields.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class BlogPost(Document):
|
class BlogPost(Document):
|
||||||
content = StringField()
|
content = StringField()
|
||||||
authors = ListField(ReferenceField(
|
authors = ListField(ReferenceField(
|
||||||
@@ -2022,7 +1969,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.Person, reverse_delete_rule=NULLIFY))
|
self.Person, reverse_delete_rule=NULLIFY))
|
||||||
|
|
||||||
self.Person.drop_collection()
|
self.Person.drop_collection()
|
||||||
|
|
||||||
BlogPost.drop_collection()
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
author = self.Person(name='Test User')
|
author = self.Person(name='Test User')
|
||||||
@@ -2046,10 +1992,10 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(BlogPost.objects.count(), 0)
|
self.assertEqual(BlogPost.objects.count(), 0)
|
||||||
|
|
||||||
def test_reverse_delete_rule_cascade_triggers_pre_delete_signal(self):
|
def test_reverse_delete_rule_cascade_triggers_pre_delete_signal(self):
|
||||||
""" ensure the pre_delete signal is triggered upon a cascading deletion
|
"""Ensure the pre_delete signal is triggered upon a cascading
|
||||||
setup a blog post with content, an author and editor
|
deletion setup a blog post with content, an author and editor
|
||||||
delete the author which triggers deletion of blogpost via cascade
|
delete the author which triggers deletion of blogpost via
|
||||||
blog post's pre_delete signal alters an editor attribute
|
cascade blog post's pre_delete signal alters an editor attribute.
|
||||||
"""
|
"""
|
||||||
class Editor(self.Person):
|
class Editor(self.Person):
|
||||||
review_queue = IntField(default=0)
|
review_queue = IntField(default=0)
|
||||||
@@ -2077,6 +2023,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
# delete the author, the post is also deleted due to the CASCADE rule
|
# delete the author, the post is also deleted due to the CASCADE rule
|
||||||
author.delete()
|
author.delete()
|
||||||
|
|
||||||
# the pre-delete signal should have decremented the editor's queue
|
# the pre-delete signal should have decremented the editor's queue
|
||||||
editor = Editor.objects(name='Max P.').get()
|
editor = Editor.objects(name='Max P.').get()
|
||||||
self.assertEqual(editor.review_queue, 0)
|
self.assertEqual(editor.review_queue, 0)
|
||||||
@@ -2085,7 +2032,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
"""Ensure that Bi-Directional relationships work with
|
"""Ensure that Bi-Directional relationships work with
|
||||||
reverse_delete_rule
|
reverse_delete_rule
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Bar(Document):
|
class Bar(Document):
|
||||||
content = StringField()
|
content = StringField()
|
||||||
foo = ReferenceField('Foo')
|
foo = ReferenceField('Foo')
|
||||||
@@ -2131,8 +2077,8 @@ class InstanceTest(unittest.TestCase):
|
|||||||
mother = ReferenceField('Person', reverse_delete_rule=DENY)
|
mother = ReferenceField('Person', reverse_delete_rule=DENY)
|
||||||
|
|
||||||
def test_reverse_delete_rule_cascade_recurs(self):
|
def test_reverse_delete_rule_cascade_recurs(self):
|
||||||
"""Ensure that a chain of documents is also deleted upon cascaded
|
"""Ensure that a chain of documents is also deleted upon
|
||||||
deletion.
|
cascaded deletion.
|
||||||
"""
|
"""
|
||||||
class BlogPost(Document):
|
class BlogPost(Document):
|
||||||
content = StringField()
|
content = StringField()
|
||||||
@@ -2162,15 +2108,10 @@ class InstanceTest(unittest.TestCase):
|
|||||||
author.delete()
|
author.delete()
|
||||||
self.assertEqual(Comment.objects.count(), 0)
|
self.assertEqual(Comment.objects.count(), 0)
|
||||||
|
|
||||||
self.Person.drop_collection()
|
|
||||||
BlogPost.drop_collection()
|
|
||||||
Comment.drop_collection()
|
|
||||||
|
|
||||||
def test_reverse_delete_rule_deny(self):
|
def test_reverse_delete_rule_deny(self):
|
||||||
"""Ensure that a document cannot be referenced if there are still
|
"""Ensure that a document cannot be referenced if there are
|
||||||
documents referring to it.
|
still documents referring to it.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class BlogPost(Document):
|
class BlogPost(Document):
|
||||||
content = StringField()
|
content = StringField()
|
||||||
author = ReferenceField(self.Person, reverse_delete_rule=DENY)
|
author = ReferenceField(self.Person, reverse_delete_rule=DENY)
|
||||||
@@ -2198,11 +2139,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
author.delete()
|
author.delete()
|
||||||
self.assertEqual(self.Person.objects.count(), 1)
|
self.assertEqual(self.Person.objects.count(), 1)
|
||||||
|
|
||||||
self.Person.drop_collection()
|
|
||||||
BlogPost.drop_collection()
|
|
||||||
|
|
||||||
def subclasses_and_unique_keys_works(self):
|
def subclasses_and_unique_keys_works(self):
|
||||||
|
|
||||||
class A(Document):
|
class A(Document):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -2218,12 +2155,9 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(A.objects.count(), 2)
|
self.assertEqual(A.objects.count(), 2)
|
||||||
self.assertEqual(B.objects.count(), 1)
|
self.assertEqual(B.objects.count(), 1)
|
||||||
A.drop_collection()
|
|
||||||
B.drop_collection()
|
|
||||||
|
|
||||||
def test_document_hash(self):
|
def test_document_hash(self):
|
||||||
"""Test document in list, dict, set
|
"""Test document in list, dict, set."""
|
||||||
"""
|
|
||||||
class User(Document):
|
class User(Document):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -2266,11 +2200,9 @@ class InstanceTest(unittest.TestCase):
|
|||||||
|
|
||||||
# in Set
|
# in Set
|
||||||
all_user_set = set(User.objects.all())
|
all_user_set = set(User.objects.all())
|
||||||
|
|
||||||
self.assertTrue(u1 in all_user_set)
|
self.assertTrue(u1 in all_user_set)
|
||||||
|
|
||||||
def test_picklable(self):
|
def test_picklable(self):
|
||||||
|
|
||||||
pickle_doc = PickleTest(number=1, string="One", lists=['1', '2'])
|
pickle_doc = PickleTest(number=1, string="One", lists=['1', '2'])
|
||||||
pickle_doc.embedded = PickleEmbedded()
|
pickle_doc.embedded = PickleEmbedded()
|
||||||
pickled_doc = pickle.dumps(pickle_doc) # make sure pickling works even before the doc is saved
|
pickled_doc = pickle.dumps(pickle_doc) # make sure pickling works even before the doc is saved
|
||||||
@@ -2296,7 +2228,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(pickle_doc.lists, ["1", "2", "3"])
|
self.assertEqual(pickle_doc.lists, ["1", "2", "3"])
|
||||||
|
|
||||||
def test_regular_document_pickle(self):
|
def test_regular_document_pickle(self):
|
||||||
|
|
||||||
pickle_doc = PickleTest(number=1, string="One", lists=['1', '2'])
|
pickle_doc = PickleTest(number=1, string="One", lists=['1', '2'])
|
||||||
pickled_doc = pickle.dumps(pickle_doc) # make sure pickling works even before the doc is saved
|
pickled_doc = pickle.dumps(pickle_doc) # make sure pickling works even before the doc is saved
|
||||||
pickle_doc.save()
|
pickle_doc.save()
|
||||||
@@ -2319,7 +2250,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
fixtures.PickleTest = PickleTest
|
fixtures.PickleTest = PickleTest
|
||||||
|
|
||||||
def test_dynamic_document_pickle(self):
|
def test_dynamic_document_pickle(self):
|
||||||
|
|
||||||
pickle_doc = PickleDynamicTest(
|
pickle_doc = PickleDynamicTest(
|
||||||
name="test", number=1, string="One", lists=['1', '2'])
|
name="test", number=1, string="One", lists=['1', '2'])
|
||||||
pickle_doc.embedded = PickleDynamicEmbedded(foo="Bar")
|
pickle_doc.embedded = PickleDynamicEmbedded(foo="Bar")
|
||||||
@@ -2358,7 +2288,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
validate = DictField()
|
validate = DictField()
|
||||||
|
|
||||||
def test_mutating_documents(self):
|
def test_mutating_documents(self):
|
||||||
|
|
||||||
class B(EmbeddedDocument):
|
class B(EmbeddedDocument):
|
||||||
field1 = StringField(default='field1')
|
field1 = StringField(default='field1')
|
||||||
|
|
||||||
@@ -2366,6 +2295,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
b = EmbeddedDocumentField(B, default=lambda: B())
|
b = EmbeddedDocumentField(B, default=lambda: B())
|
||||||
|
|
||||||
A.drop_collection()
|
A.drop_collection()
|
||||||
|
|
||||||
a = A()
|
a = A()
|
||||||
a.save()
|
a.save()
|
||||||
a.reload()
|
a.reload()
|
||||||
@@ -2389,12 +2319,13 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(a.b.field2.c_field, 'new value')
|
self.assertEqual(a.b.field2.c_field, 'new value')
|
||||||
|
|
||||||
def test_can_save_false_values(self):
|
def test_can_save_false_values(self):
|
||||||
"""Ensures you can save False values on save"""
|
"""Ensures you can save False values on save."""
|
||||||
class Doc(Document):
|
class Doc(Document):
|
||||||
foo = StringField()
|
foo = StringField()
|
||||||
archived = BooleanField(default=False, required=True)
|
archived = BooleanField(default=False, required=True)
|
||||||
|
|
||||||
Doc.drop_collection()
|
Doc.drop_collection()
|
||||||
|
|
||||||
d = Doc()
|
d = Doc()
|
||||||
d.save()
|
d.save()
|
||||||
d.archived = False
|
d.archived = False
|
||||||
@@ -2403,11 +2334,12 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(Doc.objects(archived=False).count(), 1)
|
self.assertEqual(Doc.objects(archived=False).count(), 1)
|
||||||
|
|
||||||
def test_can_save_false_values_dynamic(self):
|
def test_can_save_false_values_dynamic(self):
|
||||||
"""Ensures you can save False values on dynamic docs"""
|
"""Ensures you can save False values on dynamic docs."""
|
||||||
class Doc(DynamicDocument):
|
class Doc(DynamicDocument):
|
||||||
foo = StringField()
|
foo = StringField()
|
||||||
|
|
||||||
Doc.drop_collection()
|
Doc.drop_collection()
|
||||||
|
|
||||||
d = Doc()
|
d = Doc()
|
||||||
d.save()
|
d.save()
|
||||||
d.archived = False
|
d.archived = False
|
||||||
@@ -2447,7 +2379,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
Collection.update = orig_update
|
Collection.update = orig_update
|
||||||
|
|
||||||
def test_db_alias_tests(self):
|
def test_db_alias_tests(self):
|
||||||
""" DB Alias tests """
|
"""DB Alias tests."""
|
||||||
# mongoenginetest - Is default connection alias from setUp()
|
# mongoenginetest - Is default connection alias from setUp()
|
||||||
# Register Aliases
|
# Register Aliases
|
||||||
register_connection('testdb-1', 'mongoenginetest2')
|
register_connection('testdb-1', 'mongoenginetest2')
|
||||||
@@ -2509,8 +2441,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
get_db("testdb-3")[AuthorBooks._get_collection_name()])
|
get_db("testdb-3")[AuthorBooks._get_collection_name()])
|
||||||
|
|
||||||
def test_db_alias_overrides(self):
|
def test_db_alias_overrides(self):
|
||||||
"""db_alias can be overriden
|
"""Test db_alias can be overriden."""
|
||||||
"""
|
|
||||||
# Register a connection with db_alias testdb-2
|
# Register a connection with db_alias testdb-2
|
||||||
register_connection('testdb-2', 'mongoenginetest2')
|
register_connection('testdb-2', 'mongoenginetest2')
|
||||||
|
|
||||||
@@ -2534,8 +2465,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
B._get_collection().database.name)
|
B._get_collection().database.name)
|
||||||
|
|
||||||
def test_db_alias_propagates(self):
|
def test_db_alias_propagates(self):
|
||||||
"""db_alias propagates?
|
"""db_alias propagates?"""
|
||||||
"""
|
|
||||||
register_connection('testdb-1', 'mongoenginetest2')
|
register_connection('testdb-1', 'mongoenginetest2')
|
||||||
|
|
||||||
class A(Document):
|
class A(Document):
|
||||||
@@ -2548,8 +2478,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual('testdb-1', B._meta.get('db_alias'))
|
self.assertEqual('testdb-1', B._meta.get('db_alias'))
|
||||||
|
|
||||||
def test_db_ref_usage(self):
|
def test_db_ref_usage(self):
|
||||||
""" DB Ref usage in dict_fields"""
|
"""DB Ref usage in dict_fields."""
|
||||||
|
|
||||||
class User(Document):
|
class User(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
@@ -2784,7 +2713,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(user.thing._data['data'], [1, 2, 3])
|
self.assertEqual(user.thing._data['data'], [1, 2, 3])
|
||||||
|
|
||||||
def test_spaces_in_keys(self):
|
def test_spaces_in_keys(self):
|
||||||
|
|
||||||
class Embedded(DynamicEmbeddedDocument):
|
class Embedded(DynamicEmbeddedDocument):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -2873,7 +2801,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
log.machine = "127.0.0.1"
|
log.machine = "127.0.0.1"
|
||||||
|
|
||||||
def test_kwargs_simple(self):
|
def test_kwargs_simple(self):
|
||||||
|
|
||||||
class Embedded(EmbeddedDocument):
|
class Embedded(EmbeddedDocument):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
@@ -2893,7 +2820,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(classic_doc._data, dict_doc._data)
|
self.assertEqual(classic_doc._data, dict_doc._data)
|
||||||
|
|
||||||
def test_kwargs_complex(self):
|
def test_kwargs_complex(self):
|
||||||
|
|
||||||
class Embedded(EmbeddedDocument):
|
class Embedded(EmbeddedDocument):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
@@ -2916,36 +2842,35 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(classic_doc._data, dict_doc._data)
|
self.assertEqual(classic_doc._data, dict_doc._data)
|
||||||
|
|
||||||
def test_positional_creation(self):
|
def test_positional_creation(self):
|
||||||
"""Ensure that document may be created using positional arguments.
|
"""Ensure that document may be created using positional arguments."""
|
||||||
"""
|
|
||||||
person = self.Person("Test User", 42)
|
person = self.Person("Test User", 42)
|
||||||
self.assertEqual(person.name, "Test User")
|
self.assertEqual(person.name, "Test User")
|
||||||
self.assertEqual(person.age, 42)
|
self.assertEqual(person.age, 42)
|
||||||
|
|
||||||
def test_mixed_creation(self):
|
def test_mixed_creation(self):
|
||||||
"""Ensure that document may be created using mixed arguments.
|
"""Ensure that document may be created using mixed arguments."""
|
||||||
"""
|
|
||||||
person = self.Person("Test User", age=42)
|
person = self.Person("Test User", age=42)
|
||||||
self.assertEqual(person.name, "Test User")
|
self.assertEqual(person.name, "Test User")
|
||||||
self.assertEqual(person.age, 42)
|
self.assertEqual(person.age, 42)
|
||||||
|
|
||||||
def test_positional_creation_embedded(self):
|
def test_positional_creation_embedded(self):
|
||||||
"""Ensure that embedded document may be created using positional arguments.
|
"""Ensure that embedded document may be created using positional
|
||||||
|
arguments.
|
||||||
"""
|
"""
|
||||||
job = self.Job("Test Job", 4)
|
job = self.Job("Test Job", 4)
|
||||||
self.assertEqual(job.name, "Test Job")
|
self.assertEqual(job.name, "Test Job")
|
||||||
self.assertEqual(job.years, 4)
|
self.assertEqual(job.years, 4)
|
||||||
|
|
||||||
def test_mixed_creation_embedded(self):
|
def test_mixed_creation_embedded(self):
|
||||||
"""Ensure that embedded document may be created using mixed arguments.
|
"""Ensure that embedded document may be created using mixed
|
||||||
|
arguments.
|
||||||
"""
|
"""
|
||||||
job = self.Job("Test Job", years=4)
|
job = self.Job("Test Job", years=4)
|
||||||
self.assertEqual(job.name, "Test Job")
|
self.assertEqual(job.name, "Test Job")
|
||||||
self.assertEqual(job.years, 4)
|
self.assertEqual(job.years, 4)
|
||||||
|
|
||||||
def test_mixed_creation_dynamic(self):
|
def test_mixed_creation_dynamic(self):
|
||||||
"""Ensure that document may be created using mixed arguments.
|
"""Ensure that document may be created using mixed arguments."""
|
||||||
"""
|
|
||||||
class Person(DynamicDocument):
|
class Person(DynamicDocument):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
@@ -2954,14 +2879,14 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(person.age, 42)
|
self.assertEqual(person.age, 42)
|
||||||
|
|
||||||
def test_bad_mixed_creation(self):
|
def test_bad_mixed_creation(self):
|
||||||
"""Ensure that document gives correct error when duplicating arguments
|
"""Ensure that document gives correct error when duplicating
|
||||||
|
arguments.
|
||||||
"""
|
"""
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
return self.Person("Test User", 42, name="Bad User")
|
return self.Person("Test User", 42, name="Bad User")
|
||||||
|
|
||||||
def test_data_contains_id_field(self):
|
def test_data_contains_id_field(self):
|
||||||
"""Ensure that asking for _data returns 'id'
|
"""Ensure that asking for _data returns 'id'."""
|
||||||
"""
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
name = StringField()
|
name = StringField()
|
||||||
|
|
||||||
@@ -2973,7 +2898,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(person._data.get('id'), person.id)
|
self.assertEqual(person._data.get('id'), person.id)
|
||||||
|
|
||||||
def test_complex_nesting_document_and_embedded_document(self):
|
def test_complex_nesting_document_and_embedded_document(self):
|
||||||
|
|
||||||
class Macro(EmbeddedDocument):
|
class Macro(EmbeddedDocument):
|
||||||
value = DynamicField(default="UNDEFINED")
|
value = DynamicField(default="UNDEFINED")
|
||||||
|
|
||||||
@@ -3016,7 +2940,6 @@ class InstanceTest(unittest.TestCase):
|
|||||||
system.nodes["node"].parameters["param"].macros["test"].value)
|
system.nodes["node"].parameters["param"].macros["test"].value)
|
||||||
|
|
||||||
def test_embedded_document_equality(self):
|
def test_embedded_document_equality(self):
|
||||||
|
|
||||||
class Test(Document):
|
class Test(Document):
|
||||||
field = StringField(required=True)
|
field = StringField(required=True)
|
||||||
|
|
||||||
@@ -3202,8 +3125,7 @@ class InstanceTest(unittest.TestCase):
|
|||||||
self.assertEqual(idx, 2)
|
self.assertEqual(idx, 2)
|
||||||
|
|
||||||
def test_falsey_pk(self):
|
def test_falsey_pk(self):
|
||||||
"""Ensure that we can create and update a document with Falsey PK.
|
"""Ensure that we can create and update a document with Falsey PK."""
|
||||||
"""
|
|
||||||
class Person(Document):
|
class Person(Document):
|
||||||
age = IntField(primary_key=True)
|
age = IntField(primary_key=True)
|
||||||
height = FloatField()
|
height = FloatField()
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -198,19 +198,6 @@ class ConnectionTest(unittest.TestCase):
|
|||||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||||
self.assertEqual(db.name, 'test')
|
self.assertEqual(db.name, 'test')
|
||||||
|
|
||||||
def test_connect_uri_with_replicaset(self):
|
|
||||||
"""Ensure connect() works when specifying a replicaSet."""
|
|
||||||
if IS_PYMONGO_3:
|
|
||||||
c = connect(host='mongodb://localhost/test?replicaSet=local-rs')
|
|
||||||
db = get_db()
|
|
||||||
self.assertTrue(isinstance(db, pymongo.database.Database))
|
|
||||||
self.assertEqual(db.name, 'test')
|
|
||||||
else:
|
|
||||||
# PyMongo < v3.x raises an exception:
|
|
||||||
# "localhost:27017 is not a member of replica set local-rs"
|
|
||||||
with self.assertRaises(MongoEngineConnectionError):
|
|
||||||
c = connect(host='mongodb://localhost/test?replicaSet=local-rs')
|
|
||||||
|
|
||||||
def test_uri_without_credentials_doesnt_override_conn_settings(self):
|
def test_uri_without_credentials_doesnt_override_conn_settings(self):
|
||||||
"""Ensure connect() uses the username & password params if the URI
|
"""Ensure connect() uses the username & password params if the URI
|
||||||
doesn't explicitly specify them.
|
doesn't explicitly specify them.
|
||||||
@@ -332,6 +319,38 @@ class ConnectionTest(unittest.TestCase):
|
|||||||
self.assertEqual(dict(conn1.write_concern), {'w': 1, 'j': True})
|
self.assertEqual(dict(conn1.write_concern), {'w': 1, 'j': True})
|
||||||
self.assertEqual(dict(conn2.write_concern), {'w': 1, 'j': True})
|
self.assertEqual(dict(conn2.write_concern), {'w': 1, 'j': True})
|
||||||
|
|
||||||
|
def test_connect_with_replicaset_via_uri(self):
|
||||||
|
"""Ensure connect() works when specifying a replicaSet via the
|
||||||
|
MongoDB URI.
|
||||||
|
"""
|
||||||
|
if IS_PYMONGO_3:
|
||||||
|
c = connect(host='mongodb://localhost/test?replicaSet=local-rs')
|
||||||
|
db = get_db()
|
||||||
|
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||||
|
self.assertEqual(db.name, 'test')
|
||||||
|
else:
|
||||||
|
# PyMongo < v3.x raises an exception:
|
||||||
|
# "localhost:27017 is not a member of replica set local-rs"
|
||||||
|
with self.assertRaises(MongoEngineConnectionError):
|
||||||
|
c = connect(host='mongodb://localhost/test?replicaSet=local-rs')
|
||||||
|
|
||||||
|
def test_connect_with_replicaset_via_kwargs(self):
|
||||||
|
"""Ensure connect() works when specifying a replicaSet via the
|
||||||
|
connection kwargs
|
||||||
|
"""
|
||||||
|
if IS_PYMONGO_3:
|
||||||
|
c = connect(replicaset='local-rs')
|
||||||
|
self.assertEqual(c._MongoClient__options.replica_set_name,
|
||||||
|
'local-rs')
|
||||||
|
db = get_db()
|
||||||
|
self.assertTrue(isinstance(db, pymongo.database.Database))
|
||||||
|
self.assertEqual(db.name, 'test')
|
||||||
|
else:
|
||||||
|
# PyMongo < v3.x raises an exception:
|
||||||
|
# "localhost:27017 is not a member of replica set local-rs"
|
||||||
|
with self.assertRaises(MongoEngineConnectionError):
|
||||||
|
c = connect(replicaset='local-rs')
|
||||||
|
|
||||||
def test_datetime(self):
|
def test_datetime(self):
|
||||||
connect('mongoenginetest', tz_aware=True)
|
connect('mongoenginetest', tz_aware=True)
|
||||||
d = datetime.datetime(2010, 5, 5, tzinfo=utc)
|
d = datetime.datetime(2010, 5, 5, tzinfo=utc)
|
||||||
|
|||||||
Reference in New Issue
Block a user