I am trying to delete batches of entities of a single Kind from my datastore using the defined function findpins
below. The parameter limit
tells the number of entities from the Kind Pin
to delete.
In practice, limit
will be just below 20000 to make the daily deletes free. I am doing a keys_only
query to avoid reading each entity.
But in testing my code I get the following error.
AttributeError: 'Key' object has no attribute 'delete'
Update 0
If, instead of pin.delete()
, I use print pin
I see two 80 character strings which I assume are 2 Keys. But I don't know how to use the Keys for deletion.
Update 1
If, instead of keys_only=True
, I use keys_only=False
I accomplish the delete. But then I have encountered a potential charge for a read which is costly. Is that correct?
How can I fix this?
If you see other issues with my strategy, please say so, too.
Update 2 My revised Python code based on @jccampanero's suggestion is promising but so far fails in isinstance
because of its arguments Model
and Key
. First I got the error message NameError: global name 'Model' is not defined
. But then when I replaced Model
with Pin
I get the error NameError: global name 'Key' is not defined
and I cannot imagine what to replace Key
with. I don't know what I'm doing with these new definitions, and am particularly uncomfortable with the params **kwargs
. So I could really use some help here. Am I on the right track?
Python code (editted with 2 new imports, 2 new def's and 1 new delete command) :
import os
import pprint
from google.appengine.ext import db
from google.appengine.api import datastore
from google.appengine.datastore import datastore_rpc
def delete_async(models, **kwargs):
if isinstance(models, (basestring, Model, Key)):
models = [models]
else:
try:
models = iter(models)
except TypeError:
models = [models]
keys = [_coerce_to_key(v) for v in models]
return datastore.DeleteAsync(keys, **kwargs)
def delete(models, **kwargs):
delete_async(models, **kwargs).get_result()
class Pin(db.Model):
name = db.StringProperty()
def findpins(limit):
pin_query = Pin.all(keys_only=True)
for pin in pin_query.run(limit=limit):
# was: pin.delete()
delete(pin)
findpins(2)
CodePudding user response:
According to the source code of the library, you can use the delete
function for that purpose: it accepts the key of the record you want to delete.
Please, consider the following modification in your code (note the use of the aforementioned db.delete
function):
import os
import pprint
from google.appengine.ext import db
class Pin(db.Model):
name = db.StringProperty()
def findpins(limit):
pin_query = Pin.all(keys_only=True)
for pin in pin_query.run(limit=limit):
db.delete(pin)
findpins(2)
CodePudding user response:
You just have to modify 2 lines of your code and it should work.
if isinstance(models, (basestring, db.Model, db.Key)):
db.delete(pin)
Final Code:
import os
import pprint
from google.appengine.ext import db
from google.appengine.api import datastore
from google.appengine.datastore import datastore_rpc
def delete_async(models, **kwargs):
if isinstance(models, (basestring, db.Model, db.Key)):
models = [models]
else:
try:
models = iter(models)
except TypeError:
models = [models]
keys = [_coerce_to_key(v) for v in models]
return datastore.DeleteAsync(keys, **kwargs)
def delete(models, **kwargs):
delete_async(models, **kwargs).get_result()
class Pin(db.Model):
name = db.StringProperty()
def findpins(limit):
pin_query = Pin.all(keys_only=True)
for pin in pin_query.run(limit=limit):
# was: pin.delete()
db.delete(pin)
findpins(2)