简体   繁体   中英

How to remove a single item in StructuredProperty ( or Repeated Property) of an NDB database?

I have an ndb.Model which contains one Repeated property in it.

class Resort(ndb.Model):
    name        = ndb.StringProperty()
    hotel_keys  = ndb.KeyProperty(repeated=True)

I put a list of "keys" into "hotel_keys" property. Then I need to delete a single item in it (let's say by id) How could I do that?

resort = Resort.get_by_id(resort_id)
for hotel_key in resort.hotel.keys:
     if hotel_key.id() == id:
         del ???
resort.put()

I would appreciate any help. Thanks.

Here is a way to delete it without iteration and remove: (only works for repeated keyproperty since it has an actualy string representation with single property id, for repeated structured property you'll have to loop and check against the property you want to delete get index and delete after the loop)

key_to_delete = ndb.Key(ModelOfThatId, id)

if key_to_delete in resort.hotel_keys:
    idx = resort.hotel_keys.index(key_to_delete)
    del resort.hotel_keys[idx]
    resort.put()

THe repeated property is just a list, and the entity you are putting in the list is fairly simple. So you can just use pop and index rather than looping. The put()

dev~fish-and-lily> class Resort(ndb.Model):
...    hotel_keys = ndb.KeyProperty(repeated=True)
... 
dev~xxx-and-zzz> y = XX()
dev~xxx-and-zzz> y.hotel_keys.append(ndb.Key('abc',1))
dev~xxx-and-zzz> y.hotel_keys.append(ndb.Key('abc',2))
dev~xxx-and-zzz> y.hotel_keys.append(ndb.Key('abc',3))
dev~xxx-and-zzz> y.hotel_keys.index(ndb.Key('abc',3))
2
dev~xxx-and-zzz> y.hotel_keys.pop(2)
Key('abc', 3)
dev~xxx-and-zzz> y.hotel_keys
[Key('abc', 1), Key('abc', 2)]
dev~xxx-and-zzz> 

Repeated properties are lists and iterating a list and removing a value from it at the same time is not possible. You should create a copy of the list without the value that you want removed - see this question: Remove items from a list while iterating

I found that using the list's remove() method works well:

if some_hotel_key in resort.hotel_keys:
     resort.hotel_keys.remove(some_hotel_key)
resort.put()

Note that I'm using actual NDB Keys here, not key ID's. This assumes that the hotel_keys property is a list of keys of some other model class , like. Like your Resort class should be updated to have:

hotel_keys = ndb.KeyProperty(kind=Hotel, repeated=True)

And then be sure you have a class Hotel(ndb.Model) defined somewhere. this would then let you define:

some_hotel_key = ndb.Key(Hotel, 'myHotel')

To reiterate a note I left above: it will only pop 1 instance of the value. If there's a risk your .hotel_keys property has duplicates, be sure to handle that. I'd use resort.hotel_keys = list(set(resort.hotel_keys)) before getting the index for deletion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM