diff --git a/cassandra/cqlengine/query.py b/cassandra/cqlengine/query.py index cf682c7a..dd9bffad 100644 --- a/cassandra/cqlengine/query.py +++ b/cassandra/cqlengine/query.py @@ -274,6 +274,9 @@ class ContextQuery(object): A Context manager to allow a Model to switch context easily. Presently, the context only specifies a keyspace for model IO. + :param *args: One or more models. A model should be a class type, not an instance. + :param **kwargs: (optional) Context parameters: can be *keyspace* or *connection* + For example: .. code-block:: python @@ -293,10 +296,6 @@ class ContextQuery(object): """ def __init__(self, *args, **kwargs): - """ - :param *args: One or more models. A model should be a class type, not an instance. - :param **kwargs: (optional) Context parameters: can be keyspace or connection - """ from cassandra.cqlengine import models self.models = [] @@ -1007,7 +1006,7 @@ class AbstractQuerySet(object): def using(self, keyspace=None, connection=None): """ - Change the context on-the-fly of the Model class (connection, keyspace) + Change the context on-the-fly of the Model class (keyspace, connection) """ if connection and self._batch: diff --git a/docs/api/cassandra/cqlengine/connection.rst b/docs/api/cassandra/cqlengine/connection.rst index 184a6026..0f584fcc 100644 --- a/docs/api/cassandra/cqlengine/connection.rst +++ b/docs/api/cassandra/cqlengine/connection.rst @@ -8,3 +8,9 @@ .. autofunction:: set_session .. autofunction:: setup + +.. autofunction:: register_connection + +.. autofunction:: unregister_connection + +.. autofunction:: set_default_connection diff --git a/docs/api/cassandra/cqlengine/models.rst b/docs/api/cassandra/cqlengine/models.rst index fd081fb1..b3695e8a 100644 --- a/docs/api/cassandra/cqlengine/models.rst +++ b/docs/api/cassandra/cqlengine/models.rst @@ -32,6 +32,8 @@ Model .. autoattribute:: __keyspace__ + .. autoattribute:: __connection__ + .. attribute:: __default_ttl__ :annotation: = None @@ -169,6 +171,10 @@ Model Sets the ttl values to run instance updates and inserts queries with. + .. method:: using(keyspace=None, connection=None) + + Change the context on the fly of the model instance (keyspace, connection) + .. automethod:: column_family_name Models also support dict-like access: diff --git a/docs/api/cassandra/cqlengine/query.rst b/docs/api/cassandra/cqlengine/query.rst index c0c8f285..ce8f764b 100644 --- a/docs/api/cassandra/cqlengine/query.rst +++ b/docs/api/cassandra/cqlengine/query.rst @@ -50,6 +50,8 @@ The methods here are used to filter, order, and constrain results. .. automethod:: ttl + .. automethod:: using + .. _blind_updates: .. automethod:: update diff --git a/docs/cqlengine/batches.rst b/docs/cqlengine/batches.rst index a567e31c..29520674 100644 --- a/docs/cqlengine/batches.rst +++ b/docs/cqlengine/batches.rst @@ -12,7 +12,7 @@ Batch Query General Use Pattern .. code-block:: python - from cqlengine import BatchQuery + from cassandra.cqlengine import BatchQuery #using a context manager with BatchQuery() as b: @@ -102,7 +102,7 @@ Logged vs Unlogged Batches .. code-block:: python - from cqlengine.query import BatchType + from cassandra.cqlengine.query import BatchType with BatchQuery(batch_type=BatchType.Unlogged) as b: LogEntry.batch(b).create(k=1, v=1) LogEntry.batch(b).create(k=1, v=2) diff --git a/docs/cqlengine/connections.rst b/docs/cqlengine/connections.rst new file mode 100644 index 00000000..922dbb5d --- /dev/null +++ b/docs/cqlengine/connections.rst @@ -0,0 +1,126 @@ +========================== +Connections (experimental) +========================== + +Connections are experimental and aimed to ease the use of multiple sessions with cqlengine. Connections can be set on a model class, per query or using a context manager. + + +Register a new connection +========================= + +To use cqlengine, you need at least a default connection. This is currently done automatically under the hood with :func:`connection.setup <.connection.setup>`. If you want to use another cluster/session, you need to register a new cqlengine connection. You register a connection with :func:`~.connection.register_connection` + + .. code-block:: python + + from cassandra.cqlengine import connection + + connection.setup(['127.0.0.1') + connection.register_connection('cluster2', ['127.0.0.2']) + +Change the default connection +============================= + +You can change the default cqlengine connection on registration: + + .. code-block:: python + + from cassandra.cqlengine import connection + + connection.register_connection('cluster2', ['127.0.0.2'] default=True) + +or on the fly using :func:`~.connection.set_default_connection` + + .. code-block:: python + + connection.set_default_connection('cluster2') + +Unregister a connection +======================= + +You can unregister a connection using :func:`~.connection.unregister_connection`: + + .. code-block:: python + + connection.unregister_connection('cluster2') + +Management +========== + +When using multiples connections, you also need to sync your models on all connections (and keyspaces) that you need operate on. Management commands have been improved to ease this part. Here is an example: + + .. code-block:: python + + from cassandra.cqlengine import management + + keyspaces = ['ks1', 'ks2'] + conns = ['cluster1', 'cluster2'] + + # registers your connections + # ... + + # create all keyspaces on all connections + for ks in keyspaces: + management.create_simple_keyspace(ks, connections=conns) + + # define your Automobile model + # ... + + # sync your models + management.sync_table(Automobile, keyspaces=keyspaces, connections=conns) + + +Connection Selection +==================== + +cqlengine will select the default connection, unless your specify a connection using one of the following methods. + +Default Model Connection +------------------------ + +You can specify a default connection per model: + + .. code-block:: python + + class Automobile(Model): + __keyspace__ = 'test' + __connection__ = 'cluster2' + manufacturer = columns.Text(primary_key=True) + year = columns.Integer(primary_key=True) + model = columns.Text(primary_key=True) + + print len(Automobile.objects.all()) # executed on the connection 'cluster2' + +QuerySet and model instance +--------------------------- + +You can use the :attr:`using() <.query.ModelQuerySet.using>` method to select a connection (or keyspace): + + .. code-block:: python + + Automobile.objects.using(connection='cluster1').create(manufacturer='honda', year=2010, model='civic') + q = Automobile.objects.filter(manufacturer='Tesla') + autos = q.using(keyspace='ks2, connection='cluster2').all() + + for auto in autos: + auto.using(connection='cluster1').save() + +Context Manager +--------------- + +You can use the ContextQuery as well to select a connection: + + .. code-block:: python + + with ContextQuery(Automobile, connection='cluster1') as A: + A.objects.filter(manufacturer='honda').all() # executed on 'cluster1' + + +BatchQuery +---------- + +With a BatchQuery, you can select the connection with the context manager. Note that all operations in the batch need to use the same connection. + + .. code-block:: python + + with BatchQuery(connection='cluster1') as b: + Automobile.objects.batch(b).create(manufacturer='honda', year=2010, model='civic') diff --git a/docs/cqlengine/models.rst b/docs/cqlengine/models.rst index dffd06fb..c0ba3901 100644 --- a/docs/cqlengine/models.rst +++ b/docs/cqlengine/models.rst @@ -119,7 +119,7 @@ extend the model's validation method: if self.name == 'jon': raise ValidationError('no jon\'s allowed') -*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cqlengine import ValidationError``) +*Note*: while not required, the convention is to raise a ``ValidationError`` (``from cassandra.cqlengine import ValidationError``) if validation fails. .. _model_inheritance: diff --git a/docs/cqlengine/queryset.rst b/docs/cqlengine/queryset.rst index c9c33932..6af2e05f 100644 --- a/docs/cqlengine/queryset.rst +++ b/docs/cqlengine/queryset.rst @@ -387,10 +387,10 @@ Named tables are a way of querying a table without creating an class. They're u .. code-block:: python - from cqlengine.connection import setup + from cassandra.cqlengine.connection import setup setup("127.0.0.1", "cqlengine_test") - from cqlengine.named import NamedTable + from cassandra.cqlengine.named import NamedTable user = NamedTable("cqlengine_test", "user") user.objects() user.objects()[0] diff --git a/docs/cqlengine/third_party.rst b/docs/cqlengine/third_party.rst index 997a8a25..20c26df3 100644 --- a/docs/cqlengine/third_party.rst +++ b/docs/cqlengine/third_party.rst @@ -13,8 +13,8 @@ Here's how, in substance, CQLengine can be plugged to `Celery from celery import Celery from celery.signals import worker_process_init, beat_init - from cqlengine import connection - from cqlengine.connection import ( + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( cluster as cql_cluster, session as cql_session) def cassandra_init(**kwargs): @@ -40,8 +40,8 @@ This is the code required for proper connection handling of CQLengine for a .. code-block:: python - from cqlengine import connection - from cqlengine.connection import ( + from cassandra.cqlengine import connection + from cassandra.cqlengine.connection import ( cluster as cql_cluster, session as cql_session) try: diff --git a/docs/cqlengine/upgrade_guide.rst b/docs/cqlengine/upgrade_guide.rst index ee524cc7..5b0ab393 100644 --- a/docs/cqlengine/upgrade_guide.rst +++ b/docs/cqlengine/upgrade_guide.rst @@ -40,7 +40,7 @@ Imports cqlengine is now integrated as a sub-package of the driver base package 'cassandra'. Upgrading will require adjusting imports to cqlengine. For example:: - from cqlengine import columns + from cassandra.cqlengine import columns is now:: diff --git a/docs/object_mapper.rst b/docs/object_mapper.rst index 4e389940..4379434f 100644 --- a/docs/object_mapper.rst +++ b/docs/object_mapper.rst @@ -19,6 +19,9 @@ Contents :doc:`cqlengine/batches` Working with batch mutations +:doc:`cqlengine/connections` + Working with multiple sessions + :ref:`API Documentation ` Index of API documentation @@ -34,6 +37,7 @@ Contents cqlengine/models cqlengine/queryset cqlengine/batches + cqlengine/connections cqlengine/third_party cqlengine/faq