Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AppEngine id/key/from_path is quite confusing what should I use

I am back into AppEngine development. And I am quite hang up with the Datastorage.

I am used to "ids", building the website with links like "/view?id=322345" gets me the GuestBook entry with this id voilà.

But in AppEngine I always see the db.Key.from_path() method called and other stuff like "Ancestors" and "parents".

In my project I have simple relationships like User->Phonenumbers, and I want to inspect each User via a GET url appending something id-like. Should I use the User models key() or how is this in AppEngine achieved?

Currently if I want to add i.e. a PhoneNumber to the User I write the following:

class JoinHandler(webapp2.RequestHandler):
    def get(self):
        user_key = self.request.get('rlm')
        fon_number = PhoneNumber()
        fon_number.country = "deDE"
        fon_number.user = db.Key(user_key)
        fon_number.put()
        self.redirect("/")
like image 506
Julius F Avatar asked Dec 20 '22 23:12

Julius F


1 Answers

If you are using the numeric ids that are automatically assigned by the datastore when you put an entity, you can then retrieve the entity with the model's get_by_id method:

class User(db.Model):
    name = db.StringProperty()
    # etc.

def AddUser(webapp2.RequestHandler):
    def get(self):
        newUser = User()
        newUser.name = self.request.get('name')
        # etc. assign all model properties
        newUser.put()
        # now, newUser.Key().id() contains the auto-assigned numeric id.
        # we can pass this value to our template and get it back via
        # a form paramter for subsequent operations.

def ShowUser(webapp2.RequestHandler):
    def get(self):
        user_to_show_id = self.request.get('id')
        user_to_show = User.get_by_id(user_to_show_id)
        if user_to_show is not None:
            # populate the template parameters with the users's data
            # and render the template
        else:
            # The requested user does not exist, so
            # render an error message/page.

Now, if you also want to store phone number entities that belong to a given user, you make store them such that their parent is the User entity. This puts them in the User's entity group and entities that are in an entity group can be queried together more quickly than if they are stored with parents.

Let's say that any User can have any given number of Phonenumber entities associated with it:

class Phonenumber(db.Model):
    number_type = db.StringProperty()
    number = db.StringProperty()

We'll add a method to the User class:

def AddNumber(self, new_number_type, new_number):
    new_number = Phonenumber(parent=self, number_type=new_number_type, number=new_number)
    # In this case, self is the User entity, and by saying parent=self, we're putting
    # this Phonenumber entity into User's entity group.
    new_number.put()

def GetPhoneNumber(self):
    # Now, getting all of User's phone numbers is a simple as a query with an
    # Ancestor clause:
    users_numbers = Phonenumber.all().ancestor(self).fetch(1000)

   return users_numbers

Obviously, these classes are naive and straight off the top of my head, but I hope that they'll help you understand both id's and ancestor relationships. Often times, you won't have to use Key() to manually create keys at all. Don't go that route unless you really need to. Still, understanding how Keys work is good for really understanding AppEngine, so dive in and experiment if you feel like it.

I think that those were your two main questions, yeah? If you have others, go ahead and leave a comment, and I'll edit my answer.

like image 68
Adam Crossland Avatar answered Feb 16 '23 00:02

Adam Crossland