In Google App Engine, using NDB, how can an entire namespace be entirely removed?
The following code removes all entities:
def delete(namespace):
namespace_manager.set_namespace(namespace)
for kind in ndb.metadata.get_kinds():
keys = [ k for k in ndb.Query(kind=kind).iter(keys_only=True) ]
ndb.delete_multi( keys )
However, on the dev server, the namespace is still there when calling:
ndb.metadata.get_namespaces()
and, in production, exceptions are raised when trying to delete system kind, for example:
illegal key.path.element.type: __Stat_Ns_Kind__
How can a namespace be wiped out entirely?
As pointed out by @jeremydw, namespace information is stored in a __namespace__
kind. However, this does not behave as a normal kind and in particular, deleting entities does not seem to have any effect:
id_namepace = 'some_test'
print list( ndb.Query(kind='__namespace__') )
# id_namespace is not present
# SomeModel is some existing model
key_entity = ndb.Key('SomeModel', 'some_string_id', namespace=id_namepace)
entity = datastore.CustomerAction(key=key_entity)
entity.put()
print list( ndb.Query(kind='__namespace__') )
# id_namespace is present (expected, namespace was implicitly created by adding one entity in it)
key_entity.delete()
print list( ndb.Query(kind='__namespace__') )
# id_namespace is present (expected, namespace still exists but contains no entities)
key_namespace = ndb.metadata.Namespace.key_for_namespace(id_namepace)
key_namespace.delete()
print list( ndb.Query(kind='__namespace__') )
# id_namespace is still present (not expected, kind='__namespace__' does not behave as a normal kind)
Looking at the actual implementation of
ndb.metadata.get_namespaces
in the SDK (https://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/ndb/metadata.py#224), it looks like the list of namespaces is stored in Datastore itself, in a model namedNamespace
with kind__namespace__
.While I haven't attempted this ever myself, perhaps you can find the corresponding entity in the Datastore for the namespace that you want to obliterate, and then delete it. Then, next time you call
ndb.metadata.get_namespaces
, the query results should not include the entity for the namespace that you just deleted.