0
votes

I'm going in circles on getting the id of NDB Datastore.

I have setup the webapp2.RequestHandler to catch the email and get the ID. Basically my goal is to delete an entity, but if I pass the email address to get the ID of the entity, I'm stump, because it gives me results I was just getting. I used ID instead of key_name.

I tried finding the ID by querying via email, but it seems like using query does not have a method attribute to find the id.

def get(self,email):
  user = users.get_current_user()
  if user:
    user_key = ndb.Key('UserPrefs',user.email())
    contacts = Contact.query(Contact.email==email,ancestor=user_key)
    self.response.write(contacts.id) # there is no attribute such as Contact.id

I tried to find the ID by getting the key, but when I displayed the key, it showed me whatever value I have in the email variable

def get(self,email):
  user = users.get_current_user()
  if user:
    user_key = ndb.Key('UserPrefs',user.email())
    contact_key = ndb.Key('Contact',email,parent=user_key)
    self.response.write(contact_key.id())

Real Question: So, given that I do not have the ID, how do I find the correct ID inside an entity if I saved my entities via id and not key_name?

Here are the mixture of codes that I'm trying out.

def get(self,email):
  user = users.get_current_user()
  if user:
    user_key = ndb.Key('UserPrefs',user.email())
    contact_key = ndb.Key('Contact',email,parent=user_key)
    contacts = Contact.query(Contact.email==email,ancestor=user_key)
    contact = contacts.get()
    contact_key.delete()
    # self.response.write(contact.name) # this works
    self.response.write(contact_key.id()) # this does not work because I do not have the entity id, and I'd like to get it blindfolded. Is there a way?

Here is my Model for Contact.

class Contact(ndb.Model):
  name = ndb.StringProperty()
  phone = ndb.StringProperty()
  email = ndb.StringProperty()
  dateCreated = ndb.DateTimeProperty(auto_now_add=True)
  dateUpdated = ndb.DateTimeProperty(auto_now=True)
2

2 Answers

2
votes

The docs state:

The identifier may be either a key "name" string assigned by the application or an integer numeric ID generated automatically by the Datastore.

Since you are defining the name property on your Contact class, this is used as the identifier. (You don't want that because in real world different users can have same names)

So if you want NDB to generate numeric IDs for your entities, rename the name property to something else, e.g. username.

Update: let's go step by step:

Problem with the first example is that you are trying to get id on the Query. Query class has no id property defined on it. You should call get() on it:

# get() or fetch() should be called on query to return some data
contacts = Contact.query(Contact.email==email,ancestor=user_key).get()
self.response.write(contacts.id) # there is no attribute such as Contact.id

Problem with the second piece of code is that you are just initialising a Key and providing email as id - the second param of constructor is the id and you are providing email as value. Hence you are getting the email out. Also, there is no database operation here.

-1
votes

Note: the identifiers, which are id, key, urlsafe, or value (for the query) should be passed from the HTTP Request by webapp2.RequestHandler from a parsed url or HTTP POST, GET, PUT, or DELETE.

If you do not have any identifiers or values passed from an HTTP request, it could be difficult to access the specific entity (or the record). So, it is important to take note to pass a form of identifier or value to access the specific entity (or the record in database terms).

So, you can do the following to get the id:

Access by value:

def get(self,email):
  user = users.get_current_user()
  if user:
    user_key = ndb.Key('UserPrefs',user.email())
    contacts = Contact.query(Contact.email==email,ancestor=user_key)
    contact = contacts.get()
    id = contact.key.id() # this access the entity id directly because you have the data.
    self.response.write(id)

Access by urlsafe:

def get(self,urlString):
  user = users.get_current_user()
  if user:
    contact_key = ndb.Key(urlsafe=urlString) #urlString refers to the key of contact
    contact = contact_key.get()
    id = contact.key.id() # this access the entity id directly because you have the data.
    self.response.write(id)

Access by HTTP POST Request:

def post(self):
  user = users.get_current_user()
  if user:
    user_key = ndb.Key('UserPrefs',user.email())
    email = self.request.get('email')
    contacts = Contact.query(Contact.email==email,ancestor=user_key)
    contact = contacts.get()
    id = contact.key.id() # this access the entity id directly because you have the data.
    self.response.write(id)