def txn(entity): entity = Get(entity.key()) try: del entity[column_name] except KeyError: return Put(entity)
def txn(entity): entity = Get(entity.key()) try: entity[self.to_column_name] = entity[self.from_column_name] except KeyError: return Put(entity)
def test_key_kind(self): """ Checks that db.Keys stored in the database use proper kinds. Key kind should be the name of the table (db_table) of a model for primary keys of entities, but for foreign keys, references in general, it should be the db_table of the model the field refers to. Note that Django hides the underlying db.Key objects well, and it does work even with wrong kinds, but keeping the data consistent may be significant for external tools. TODO: Add DictField / EmbeddedModelField and nesting checks. """ parent = ParentKind.objects.create(pk=1) child = ChildKind.objects.create(pk=2, parent=parent, parents=[parent.pk]) self.assertEqual(child.parent.pk, parent.pk) self.assertEqual(child.parents[0], parent.pk) from google.appengine.api.datastore import Get from google.appengine.api.datastore_types import Key parent_key = Key.from_path(parent._meta.db_table, 1) child_key = Key.from_path(child._meta.db_table, 2) parent_entity = Get(parent_key) child_entity = Get(child_key) parent_column = child._meta.get_field('parent').column parents_column = child._meta.get_field('parents').column self.assertEqual(child_entity[parent_column], parent_key) self.assertEqual(child_entity[parents_column][0], parent_key)
def _map_entity(self, entity): new_key = Key.from_path(self.to_kind, entity.key().id_or_name(), namespace=self.to_namespace) parent = entity.parent() if parent: # If the entity has an ancestor then we need to make sure that that ancestor exists in # the new namespace as well new_parent_key = Key.from_path(parent.kind(), parent.is_or_name(), namespace=self.to_namespace) new_parent_exists = Get([new_parent_key])[0] if not new_parent_exists: raise DataError( "Trying to copy entity with an ancestor (%r) to a new namespace but the " "ancestor does not exist in the new namespace. Copy the ancestors first." % entity.key()) def txn(): existing = Get([new_key])[0] if existing and not self.overwrite_existing: return if isinstance(entity.key().id_or_name(), (int, long)): reserve_id(self.to_kind, entity.key().id_or_name(), self.to_namespace) new_entity = clone_entity(entity, new_key) Put(new_entity) RunInTransaction(txn)
def update_entity(self, pk, pk_field): gae_query = self.build_query() entity = Get(self.ops.value_for_db(pk, pk_field)) if not gae_query.matches_filters(entity): return for field, _, value in self.query.values: if hasattr(value, 'prepare_database_save'): value = value.prepare_database_save(field) else: value = field.get_db_prep_save(value, connection=self.connection) if hasattr(value, 'evaluate'): assert not value.negated value = ExpressionEvaluator(value, self.query, entity, allow_joins=False) if hasattr(value, 'as_sql'): value = value.as_sql(lambda n: n, self.connection) entity[field.column] = self.ops.value_for_db(value, field) Put(entity)
def update_entity(self, pk): gae_query = self.build_query() key = create_key(self.query.get_meta().db_table, pk) entity = Get(key) if not gae_query.matches_filters(entity): return qn = self.quote_name_unless_alias update_dict = {} for field, o, value in self.query.values: if hasattr(value, 'prepare_database_save'): value = value.prepare_database_save(field) else: value = field.get_db_prep_save(value, connection=self.connection) if hasattr(value, "evaluate"): assert not value.negated assert not value.subtree_parents value = ExpressionEvaluator(value, self.query, entity, allow_joins=False) if hasattr(value, 'as_sql'): # evaluate expression and return the new value val = value.as_sql(qn, self.connection) update_dict[field] = val else: update_dict[field] = value for field, value in update_dict.iteritems(): db_type = field.db_type(connection=self.connection) entity[qn(field.column)] = self.convert_value_for_db(db_type, value) key = Put(entity)
def test_blob(self): x = BlobModel(data='lalala') x.full_clean() x.save() e = Get(Key.from_path(BlobModel._meta.db_table, x.pk)) self.assertEqual(e['data'], x.data) x = BlobModel.objects.all()[0] self.assertEqual(e['data'], x.data)
def txn(): existing = Get([new_key])[0] if existing and not self.overwrite_existing: return if isinstance(entity.key().id_or_name(), (int, long)): reserve_id(self.to_kind, entity.key().id_or_name(), self.to_namespace) new_entity = clone_entity(entity, new_key) Put(new_entity)
def test_db_conversion(self): actual_datetime = datetime.datetime.now() entity = FieldsWithoutOptionsModel( datetime=actual_datetime, date=actual_datetime.date(), time=actual_datetime.time(), floating_point=5.97, boolean=True, null_boolean=False, text='Hallo', email='*****@*****.**', comma_seperated_integer='5,4,3,2', ip_address='194.167.1.1', slug='you slugy s**t :)', url='http://www.scholardocs.com', long_text=1000 * 'A', indexed_text='hello', integer=-400, small_integer=-4, positive_integer=400, positive_small_integer=4) entity.save() # Get the gae entity (not the django model instance) and test # if the fields have been converted right to the corresponding # GAE database types. gae_entity = Get( Key.from_path(FieldsWithoutOptionsModel._meta.db_table, entity.pk)) opts = FieldsWithoutOptionsModel._meta for name, types in [('long_text', Text), ('indexed_text', unicode), ('text', unicode), ('ip_address', unicode), ('slug', unicode), ('email', unicode), ('comma_seperated_integer', unicode), ('url', unicode), ('time', datetime.datetime), ('datetime', datetime.datetime), ('date', datetime.datetime), ('floating_point', float), ('boolean', bool), ('null_boolean', bool), ('integer', (int, long)), ('small_integer', (int, long)), ('positive_integer', (int, long)), ('positive_small_integer', (int, long))]: column = opts.get_field_by_name(name)[0].column if not isinstance(types, (list, tuple)): types = (types, ) self.assertTrue(type(gae_entity[column]) in types) # Get the model instance and check if the fields convert back # to the right types. model = FieldsWithoutOptionsModel.objects.get() for name, types in [ ('long_text', unicode), ('indexed_text', unicode), ('text', unicode), ('ip_address', unicode), ('slug', unicode), ('email', unicode), ('comma_seperated_integer', unicode), ('url', unicode), ('datetime', datetime.datetime), ('date', datetime.date), ('time', datetime.time), ('floating_point', float), ('boolean', bool), ('null_boolean', bool), ('integer', (int, long)), ('small_integer', (int, long)), ('positive_integer', (int, long)), ('positive_small_integer', (int, long))]: if not isinstance(types, (list, tuple)): types = (types, ) self.assertTrue(type(getattr(model, name)) in types)
def txn(): try: existing = Get(new_key) except datastore_errors.EntityNotFoundError: existing = None if existing and not self.overwrite_existing: return if isinstance(entity.key().id_or_name(), (int, long)): reserve_id(self.to_kind, entity.key().id_or_name(), self.namespace) new_entity = clone_entity(entity, new_key) Put(new_entity)
def get_matching_pk(self, low_mark=0, high_mark=None): if not self.included_pks: return [] results = [result for result in Get(self.included_pks) if result is not None and self.matches_filters(result)] if self.ordering: results.sort(cmp=self.order_pk_filtered) if high_mark is not None and high_mark < len(results) - 1: results = results[:high_mark] if low_mark: results = results[low_mark:] return results
def get_matching_pk(self, low_mark=0, high_mark=None): if not self.included_pks: return [] config = self.config.copy() # batch_size is not allowed for Gets if 'batch_size' in config: del config['batch_size'] results = [ result for result in Get(self.included_pks, **config) if result is not None and self.matches_filters(result) ] if self.ordering: results.sort(cmp=self.order_pk_filtered) if high_mark is not None and high_mark < len(results) - 1: results = results[:high_mark] if low_mark: results = results[low_mark:] return results
def test_options(self): entity = FieldsWithOptionsModel() # Try to save the entity with non-nullable field time set to # None, should raise an exception. self.assertRaises(DatabaseError, entity.save) time = datetime.datetime.now().time() entity.time = time entity.save() # Check if primary_key=True is set correctly for the saved entity. self.assertEquals(entity.pk, u'*****@*****.**') gae_entity = Get( Key.from_path(FieldsWithOptionsModel._meta.db_table, entity.pk)) self.assertTrue(gae_entity is not None) self.assertEquals(gae_entity.key().name(), u'*****@*****.**') # Check if default values are set correctly on the db level, # primary_key field is not stored at the db level. for field in FieldsWithOptionsModel._meta.local_fields: if field.default and field.default != NOT_PROVIDED and \ not field.primary_key: self.assertEquals(gae_entity[field.column], field.default) elif field.column == 'time': self.assertEquals( gae_entity[field.column], datetime.datetime(1970, 1, 1, time.hour, time.minute, time.second, time.microsecond)) elif field.null and field.editable: self.assertEquals(gae_entity[field.column], None) # Check if default values are set correct on the model instance # level. entity = FieldsWithOptionsModel.objects.get() for field in FieldsWithOptionsModel._meta.local_fields: if field.default and field.default != NOT_PROVIDED: self.assertEquals(getattr(entity, field.column), field.default) elif field.column == 'time': self.assertEquals(getattr(entity, field.column), time) elif field.null and field.editable: self.assertEquals(getattr(entity, field.column), None) # Check if nullable field with default values can be set to # None. entity.slug = None entity.positive_small_integer = None try: entity.save() except: self.fail() # Check if slug and positive_small_integer will be retrieved # with values set to None (on db level and model instance # level). gae_entity = Get(Key.from_path( FieldsWithOptionsModel._meta.db_table, entity.pk)) opts = FieldsWithOptionsModel._meta self.assertEquals( gae_entity[opts.get_field_by_name('slug')[0].column], None) self.assertEquals( gae_entity[opts.get_field_by_name( 'positive_small_integer')[0].column], None) # On the model instance level. entity = FieldsWithOptionsModel.objects.get() self.assertEquals( getattr(entity, opts.get_field_by_name('slug')[0].column), None) self.assertEquals( getattr(entity, opts.get_field_by_name( 'positive_small_integer')[0].column), None)
def txn(entity): entity = Get(entity.key()) entity[column_name] = value Put(entity)
def test_options(self): entity = FieldsWithOptionsModel() # try to save the entity with non-nullable field time set to None, should # raise an exception self.assertRaises(DatabaseError, entity.save) time = datetime.datetime.now().time() entity.time = time entity.save() # check if primary_key=True is set correctly for the saved entity self.assertEquals(entity.pk, u'*****@*****.**') gae_entity = Get(Key.from_path(FieldsWithOptionsModel._meta.db_table, entity.pk)) self.assertTrue(gae_entity is not None) self.assertEquals(gae_entity.key().name(), u'*****@*****.**') # check if default values are set correctly on the db level, # primary_key field is not stored at the db level for field in FieldsWithOptionsModel._meta.local_fields: if field.default and field.default != NOT_PROVIDED and not \ field.primary_key: self.assertEquals(gae_entity[field.column], field.default) elif field.column == 'time': self.assertEquals(gae_entity[field.column], datetime.datetime( 1970, 1, 1, time.hour, time.minute, time.second, time.microsecond)) elif field.null and field.editable: self.assertEquals(gae_entity[field.column], None) # check if default values are set correct on the model instance level entity = FieldsWithOptionsModel.objects.get() for field in FieldsWithOptionsModel._meta.local_fields: if field.default and field.default != NOT_PROVIDED: self.assertEquals(getattr(entity, field.column), field.default) elif field.column == 'time': self.assertEquals(getattr(entity, field.column), time) elif field.null and field.editable: self.assertEquals(getattr(entity, field.column), None) # check if nullable field with default values can be set to None entity.slug = None entity.positiv_small_integer = None try: entity.save() except: self.fail() # check if slug and positiv_small_integer will be retrieved with values # set to None (on db level and model instance level) gae_entity = Get(Key.from_path(FieldsWithOptionsModel._meta.db_table, entity.pk)) self.assertEquals(gae_entity[FieldsWithOptionsModel._meta.get_field_by_name( 'slug')[0].column], None) self.assertEquals(gae_entity[FieldsWithOptionsModel._meta.get_field_by_name( 'positiv_small_integer')[0].column], None) # on the model instance level entity = FieldsWithOptionsModel.objects.get() self.assertEquals(getattr(entity, FieldsWithOptionsModel._meta.get_field_by_name( 'slug')[0].column), None) self.assertEquals(getattr(entity, FieldsWithOptionsModel._meta.get_field_by_name( 'positiv_small_integer')[0].column), None)
def _fetch_entity(self, instance): kind = instance._meta.db_table namespace = connection.settings_dict["NAMESPACE"] return Get(Key.from_path(kind, instance.pk, namespace=namespace))