views:

271

answers:

2

Hi,

I'm new to python and I'm trying to obtain a username from the UI and query the result to get the phone book contacts of the user. But I am not able to set the user name to be a global variable to use it for multiple queries. Here's the code, I believe I am doing some syntax error/improper usage, please help out in correcting my code.

#!/usr/bin/env python

import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
import models

class showPhoneBook(db.Model):
    username = db.StringProperty(required=True)

class MyHandler(webapp.RequestHandler):
    user_name = ''
    def get(self):
        p = db.GqlQuery('SELECT * FROM UserDetails WHERE user_name = $1', user_name)
        #p = UserDetails.gql('WHERE user_name = $1', user_name)
        result1 = p.fetch(1)
        for itr1 in result1:
            userId = itr.user_id
        q = db.GqlQuery('SELECT * FROM PhoneBook WHERE user_id = :1', userId)
        #q = PhoneBook.gql('WHERE user_id = :1', userId)
        values = {
            'phoneBookValues': q
        }
        self.request.out.write(
            template.render('phonebook.html', values))
    def post(self):
        global user_name
        phoneBookuserID = showPhoneBook(
            user_name = self.request.get(
                'username'))
        self.request.out.write(user_name)
        phonebookuserID.put()
        self.redirect('/')

def main():
    app = webapp.WSGIApplication([
        (r'.*',MyHandler)], debug=True)
    wsgiref.handlers.CGIHandler().run(app)

if __name__ == "__main__":
    main()

Here UserDetails and Phonebook are my entity classes defined in my models.py

Please Help me in finding the error...or possibly get a corrected code of how to use user_name in queries after obtaining it from the UI.

+4  A: 

First and foremost, App Engine's execution model is quite "loose" -- that's why it's so scalable! When a request arrives for your URL, GAE may reuse an existing process that's already running your script, or it may start another process running the same script if that balances overall system load better; once the request is served, the process that served it may stick around or not, depending on whether the system has something better to do with the memory that the process is occupying.

You must therefore code in a way that works in either situation, without assuming that the process will stick around between requests (and without assuming it won't, either). So global variables (most always best avoided in all kinds of programming) are definitely not the way to go!

The only guaranteed way to persist things between requests is to store them in the db; sending a cookie to the user's browser as a header in your response, so said browser will send it back on the next request, is also likely to be OK (the user may decided to block his browser from accepting and resending cookies, but that's the user's decision and you can't really do much about it).

The abstract concept of a "sesssion" can encapsulate these choices and let you program at a higher level and many frameworks offer some kind of session, for example see gaeutilities unless you're already using some other web framework supplying a session abstraction.

There are many other specific issues with your code (such as confusion between username and user_name, confusion between global variables and class variables, and the lack of any assignment to either!), but in a sense these are minor issues compared to the whole conceptual problem of using globals in app engine!-)

Alex Martelli
A: 

Simples!

You seem to be storing user_name as a class variable, not a global. There is some tricky behavior here where a reference to it in a method will create an instance variable with the same name that hides the class variable.

class curious(object):
  hide = 11
  def get(self):
    return self.hide
  def put(self,x):
    print "before",self.hide
    self.hide = x
    print "after", self.hide

a = curious()
b = curious()
print a.hide,b.hide
a.put(23)
print a.hide,b.hide

Notice how object b still has a reference to the value 11, even after it is changed in a.

Don't do that. Make it a real global variable by assigning the default value outside of any class definition at the module level.

Michael Dillon