Improve connect/disconnect
- document disconnect + sample of usage - add more test cases to prevent github issues regressions
This commit is contained in:
parent
d1467c2f73
commit
b1e28d02f7
@ -5,7 +5,7 @@ Changelog
|
||||
Development
|
||||
===========
|
||||
- expose `mongoengine.connection.disconnect` and `mongoengine.connection.disconnect_all`
|
||||
- POTENTIAL BREAKING CHANGE: Fixes in connect/disconnect methods
|
||||
- POTENTIAL BREAKING CHANGE: Fixes in connect/disconnect methods #565 #566
|
||||
- calling `connect` 2 times with the same alias and different parameter will raise an error (should call disconnect first)
|
||||
- disconnect now clears `mongoengine.connection._connection_settings`
|
||||
- disconnect now clears the cached attribute `Document._collection`
|
||||
|
@ -4,9 +4,11 @@
|
||||
Connecting to MongoDB
|
||||
=====================
|
||||
|
||||
To connect to a running instance of :program:`mongod`, use the
|
||||
:func:`~mongoengine.connect` function. The first argument is the name of the
|
||||
database to connect to::
|
||||
Connections in MongoEngine are registered globally and are identified with aliases.
|
||||
If no `alias` is provided during the connection, it will use "default" as alias.
|
||||
|
||||
To connect to a running instance of :program:`mongod`, use the :func:`~mongoengine.connect`
|
||||
function. The first argument is the name of the database to connect to::
|
||||
|
||||
from mongoengine import connect
|
||||
connect('project1')
|
||||
@ -42,6 +44,9 @@ the :attr:`host` to
|
||||
will establish connection to ``production`` database using
|
||||
``admin`` username and ``qwerty`` password.
|
||||
|
||||
.. note:: Calling :func:`~mongoengine.connect` without argument will establish
|
||||
a connection to the "test" database by default
|
||||
|
||||
Replica Sets
|
||||
============
|
||||
|
||||
@ -71,6 +76,8 @@ is used.
|
||||
In the background this uses :func:`~mongoengine.register_connection` to
|
||||
store the data and you can register all aliases up front if required.
|
||||
|
||||
Documents defined in different database
|
||||
---------------------------------------
|
||||
Individual documents can also support multiple databases by providing a
|
||||
`db_alias` in their meta data. This allows :class:`~pymongo.dbref.DBRef`
|
||||
objects to point across databases and collections. Below is an example schema,
|
||||
@ -93,6 +100,33 @@ using 3 different databases to store data::
|
||||
meta = {'db_alias': 'users-books-db'}
|
||||
|
||||
|
||||
Disconnecting an existing connection
|
||||
------------------------------------
|
||||
The function :func:`~mongoengine.disconnect` can be used to
|
||||
disconnect a particular connection. This can be used to change a
|
||||
connection globally::
|
||||
|
||||
from mongoengine import connect, disconnect
|
||||
connect('a_db', alias='db1')
|
||||
|
||||
class User(Document):
|
||||
name = StringField()
|
||||
meta = {'db_alias': 'db1'}
|
||||
|
||||
disconnect(alias='db1')
|
||||
|
||||
connect('another_db', alias='db1')
|
||||
|
||||
.. note:: Calling :func:`~mongoengine.disconnect` without argument
|
||||
will disconnect the "default" connection
|
||||
|
||||
.. note:: Since connections gets registered globally, it is important
|
||||
to use the `disconnect` function from MongoEngine and not the
|
||||
`disconnect()` method of an existing connection (pymongo.MongoClient)
|
||||
|
||||
.. note:: :class:`~mongoengine.Document` are caching the pymongo collection.
|
||||
using `disconnect` ensures that it gets cleaned as well
|
||||
|
||||
Context Managers
|
||||
================
|
||||
Sometimes you may want to switch the database or collection to query against.
|
||||
@ -119,7 +153,7 @@ access to the same User document across databases::
|
||||
|
||||
Switch Collection
|
||||
-----------------
|
||||
The :class:`~mongoengine.context_managers.switch_collection` context manager
|
||||
The :func:`~mongoengine.context_managers.switch_collection` context manager
|
||||
allows you to change the collection for a given class allowing quick and easy
|
||||
access to the same Group document across collection::
|
||||
|
||||
|
@ -318,6 +318,9 @@ def connect(db=None, alias=DEFAULT_CONNECTION_NAME, **kwargs):
|
||||
Multiple databases are supported by using aliases. Provide a separate
|
||||
`alias` to connect to a different instance of :program:`mongod`.
|
||||
|
||||
In order to replace a connection identified by a given alias, you'll
|
||||
need to call ``disconnect`` first
|
||||
|
||||
See the docstring for `register_connection` for more details about all
|
||||
supported kwargs.
|
||||
|
||||
|
@ -795,13 +795,13 @@ class Document(six.with_metaclass(TopLevelDocumentMetaclass, BaseDocument)):
|
||||
.. versionchanged:: 0.10.7
|
||||
:class:`OperationError` exception raised if no collection available
|
||||
"""
|
||||
col_name = cls._get_collection_name()
|
||||
if not col_name:
|
||||
coll_name = cls._get_collection_name()
|
||||
if not coll_name:
|
||||
raise OperationError('Document %s has no collection defined '
|
||||
'(is it abstract ?)' % cls)
|
||||
cls._collection = None
|
||||
db = cls._get_db()
|
||||
db.drop_collection(col_name)
|
||||
db.drop_collection(coll_name)
|
||||
|
||||
@classmethod
|
||||
def create_index(cls, keys, background=False, **kwargs):
|
||||
|
@ -1,4 +1,6 @@
|
||||
import datetime
|
||||
|
||||
from pymongo import MongoClient
|
||||
from pymongo.errors import OperationFailure
|
||||
|
||||
try:
|
||||
@ -238,12 +240,25 @@ class ConnectionTest(unittest.TestCase):
|
||||
conn = get_connection('testdb6')
|
||||
self.assertIsInstance(conn, mongomock.MongoClient)
|
||||
|
||||
def test_disconnect(self):
|
||||
"""Ensure that the disconnect() method works properly"""
|
||||
def test_disconnect_cleans_globals(self):
|
||||
"""Ensure that the disconnect() method cleans the globals objects"""
|
||||
connections = mongoengine.connection._connections
|
||||
dbs = mongoengine.connection._dbs
|
||||
connection_settings = mongoengine.connection._connection_settings
|
||||
|
||||
connect('mongoenginetest')
|
||||
|
||||
self.assertEqual(len(connections), 1)
|
||||
self.assertEqual(len(dbs), 1)
|
||||
self.assertEqual(len(connection_settings), 1)
|
||||
|
||||
disconnect()
|
||||
self.assertEqual(len(connections), 0)
|
||||
self.assertEqual(len(dbs), 0)
|
||||
self.assertEqual(len(connection_settings), 0)
|
||||
|
||||
def test_disconnect_cleans_cached_collection_attribute_in_document(self):
|
||||
"""Ensure that the disconnect() method works properly"""
|
||||
conn1 = connect('mongoenginetest')
|
||||
|
||||
class History(Document):
|
||||
@ -252,29 +267,50 @@ class ConnectionTest(unittest.TestCase):
|
||||
self.assertIsNone(History._collection)
|
||||
|
||||
History.drop_collection()
|
||||
|
||||
History.objects.first() # will trigger the caching of _collection attribute
|
||||
|
||||
self.assertIsNotNone(History._collection)
|
||||
|
||||
self.assertEqual(len(connections), 1)
|
||||
self.assertEqual(len(dbs), 1)
|
||||
self.assertEqual(len(connection_settings), 1)
|
||||
|
||||
disconnect()
|
||||
|
||||
self.assertIsNone(History._collection)
|
||||
|
||||
self.assertEqual(len(connections), 0)
|
||||
self.assertEqual(len(dbs), 0)
|
||||
self.assertEqual(len(connection_settings), 0)
|
||||
|
||||
with self.assertRaises(MongoEngineConnectionError) as ctx_err:
|
||||
History.objects.first()
|
||||
self.assertEqual("You have not defined a default connection", str(ctx_err.exception))
|
||||
|
||||
conn2 = connect('mongoenginetest')
|
||||
History.objects.first() # Make sure its back on track
|
||||
self.assertTrue(conn1 is not conn2)
|
||||
def test_connect_disconnect_works_on_same_document(self):
|
||||
"""Ensure that the connect/disconnect works properly with a single Document"""
|
||||
db1 = 'db1'
|
||||
db2 = 'db2'
|
||||
|
||||
# Ensure freshness of the 2 databases through pymongo
|
||||
client = MongoClient('localhost', 27017)
|
||||
client.drop_database(db1)
|
||||
client.drop_database(db2)
|
||||
|
||||
# Save in db1
|
||||
connect(db1)
|
||||
|
||||
class User(Document):
|
||||
name = StringField(required=True)
|
||||
|
||||
user1 = User(name='John is in db1').save()
|
||||
disconnect()
|
||||
|
||||
# Make sure save doesnt work at this stage
|
||||
with self.assertRaises(MongoEngineConnectionError):
|
||||
User(name='Wont work').save()
|
||||
|
||||
# Save in db2
|
||||
connect(db2)
|
||||
user2 = User(name='Bob is in db2').save()
|
||||
disconnect()
|
||||
|
||||
db1_users = list(client[db1].user.find())
|
||||
self.assertEqual(db1_users, [{'_id': user1.id, 'name': 'John is in db1'}])
|
||||
db2_users = list(client[db2].user.find())
|
||||
self.assertEqual(db2_users, [{'_id': user2.id, 'name': 'Bob is in db2'}])
|
||||
|
||||
def test_disconnect_silently_pass_if_alias_does_not_exist(self):
|
||||
connections = mongoengine.connection._connections
|
||||
|
Loading…
x
Reference in New Issue
Block a user