diff --git a/cassandra/cqlengine/connection.py b/cassandra/cqlengine/connection.py index 9ce8591a..6c5d4152 100644 --- a/cassandra/cqlengine/connection.py +++ b/cassandra/cqlengine/connection.py @@ -42,17 +42,24 @@ default_consistency_level = ConsistencyLevel.ONE def default(): """ Configures the global mapper connection to localhost, using the driver defaults + (except for row_factory) """ global cluster, session cluster = Cluster() session = cluster.connect() + session.row_factory = dict_factory def set_session(s): """ Configures the global mapper connection with a preexisting :class:`cassandra.cluster.Session` + + Note: the mapper presently requires a Session :attr:`~.row_factory` set to ``dict_factory``. + This may be relaxed in the future """ global cluster, session + if s.row_factory is not dict_factory: + raise CQLEngineException("Failed to initialize: 'Session.row_factory' must be 'dict_factory'.") session = s cluster = s.cluster diff --git a/example.py b/example_core.py similarity index 100% rename from example.py rename to example_core.py diff --git a/example_mapper.py b/example_mapper.py new file mode 100755 index 00000000..eda77c2e --- /dev/null +++ b/example_mapper.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python + +# Copyright 2013-2015 DataStax, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging + +log = logging.getLogger() +log.setLevel('DEBUG') +handler = logging.StreamHandler() +handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")) +log.addHandler(handler) + +from uuid import uuid4 + +from cassandra.cqlengine import columns +from cassandra.cqlengine import connection +from cassandra.cqlengine import management +from cassandra.cqlengine.exceptions import ValidationError +from cassandra.cqlengine.models import Model +from cassandra.cqlengine.query import BatchQuery + +KEYSPACE = "testkeyspace" + + +class FamilyMembers(Model): + __keyspace__ = KEYSPACE + id = columns.UUID(primary_key=True, default=uuid4) + surname = columns.Text(primary_key=True) + name = columns.Text(primary_key=True) + birth_year = columns.Integer() + sex = columns.Text(min_length=1, max_length=1) + + def validate(self): + super(FamilyMembers, self).validate() + if self.sex and self.sex not in 'mf': + raise ValidationError("FamilyMember.sex must be one of ['m', 'f']") + + if self.birth_year and self.sex == 'f': + raise ValidationError("FamilyMember.birth_year is set, and 'a lady never tells'") + + +def main(): + connection.default() + + # Management functions would normally be used in development, and possibly for deployments. + # They are typically not part of a core application. + log.info("### creating keyspace...") + management.create_keyspace_simple(KEYSPACE, 1) + log.info("### syncing model...") + management.sync_table(FamilyMembers) + + log.info("### add entities serially") + simmons = FamilyMembers.create(surname='Simmons', name='Gene', birth_year=1949, sex='m') # default uuid is assigned + + # add members later + FamilyMembers.create(id=simmons.id, surname='Simmons', name='Nick', birth_year=1989, sex='m') + FamilyMembers.create(id=simmons.id, surname='Simmons', name='Sophie', sex='f') + # showing validation + try: + FamilyMembers.create(id=simmons.id, surname='Tweed', name='Shannon', birth_year=1957, sex='f') + except ValidationError: + log.exception('INTENTIONAL VALIDATION EXCEPTION; Failed creating instance:') + FamilyMembers.create(id=simmons.id, surname='Tweed', name='Shannon', sex='f') + + log.info("### add multiple as part of a batch") + # If creating many at one time, can use a batch to minimize round-trips + hogan_id = uuid4() + with BatchQuery() as b: + FamilyMembers.batch(b).create(id=hogan_id, surname='Hogan', name='Hulk', sex='m') + FamilyMembers.batch(b).create(id=hogan_id, surname='Hogan', name='Linda', sex='f') + FamilyMembers.batch(b).create(id=hogan_id, surname='Hogan', name='Nick', sex='m') + FamilyMembers.batch(b).create(id=hogan_id, surname='Hogan', name='Brooke', sex='f') + + log.info("### All members") + for m in FamilyMembers.all(): + print m, m.birth_year, m.sex + + log.info("### Select by partition key") + for m in FamilyMembers.objects(id=simmons.id): + print m, m.birth_year, m.sex + + log.info("### Constrain on clustering key") + for m in FamilyMembers.objects(id=simmons.id, surname=simmons.surname): + print m, m.birth_year, m.sex + + log.info("### Delete a record") + FamilyMembers(id=hogan_id, surname='Hogan', name='Linda').delete() + for m in FamilyMembers.objects(id=hogan_id): + print m, m.birth_year, m.sex + + management.drop_keyspace(KEYSPACE) + +if __name__ == "__main__": + main()