Question

Can I use context manager inside a Request Handler to manage the flow of my variables from the URL to the template?

I started from this example here

I was thinking to use it to create a class instance at the top of the handler, to run all the code I need for calculation, to close the context and to pass all the variables calculated by the class to a dictionary of parameters and finally pass them to the template. Like:

URL>>> http://domain.xx/param1/param2/

class Handler(webapp2.RequestHandler):
 def get(self, param1, param2)
  URLparams = [param1,param2]
  TEMPparams = {}
  with Foo(URLparams) as foo:
     TEMPparams['obj'] = foo.obj
     TEMPparams['obj1'] = foo.obj1
     ... 
  self.response.out.write(template, TEMPparams)

class Foo(object):
  def __init__(self, URLparams):
      ...
      ...
  def __enter__ ... :
      ... make a db query ...
  def __exit__ ... :
      ... 

What's the best implementation considering I have to perform a datastore query and some memcache set/get inside the class? For what I understood about ContextManager until now, the with statement let you make 'procedural' the execution of a class through the context methods, isn't it? I mean, the magic methods __init__() >> __enter__() >> __exit__() used with with seem to me to describe a flow. If I initialize the variables as I need, I make the query in enter() and then I delete the class' instance at __exit__(), it seems to me to simulate a procedure inside an OO paradigm.

I tested a thing like this:

class Test(webapp2.RequestHandler):
  def get(self):
    r = []
    p = {}      
    foo = Foo(r)
    with foo:
        p['obj'] = [foo, foo.bar, r]

    self.response.out.write(p)

class Foo(object):

  def __init__(self, r):
    self.bar = None
    self.r = r

  def __enter__(self):
    if self.bar != 'open':
      r = self.r
      r.append('opening the bar')
      self.bar = 'open'
    return self # this is bound to the `as` part

  def close(self):
    if self.bar != 'closed':
      r = self.r
      r.append('closing the bar')
      self.bar = 'close'

  def __exit__(self, *err):
    self.close()
    return self.r  

The foo variable is not printed on the template, even trying to convert if into a string before passing it to the template (this is not a big problem though, I would only like to know why). The result on page is:

{'obj': [, 'open', ['opening the bar', 'closing the bar']]}

Is there something wrong in this approach? Any caveat or things to take care of? Is it a correct approach to use it this way into an handler?

Was it helpful?

Solution

The best solution I could find in these days is to build a custom class to create a generic object for the tasks required in the handlers, then create an instance into the __init__() in each request handler, like:

class GenericalObject(object):
    def initialize(self, URIparams):
       # init all the self.attribute needed by my handlers

    def getDataFromDB():
       # return the DB data into a dictionary


class FirstHandler(webapp2.RequestHandler):
    def __init__(self, request, response):
       self.initialize(request, response)
       self.instance = GenericalObject()

    def get(self, URIparams1, URIparams2)
       URIparams = [URIparams1, URIparams2]
       instance = self.instance
       instance.initialize(URIparams)
       params = instance.__dict__

       data = getDataFromDB()
       params['data'] = data
       del instance

       return self.render_template('template.html', params)

class SecondHandler(webapp2.RequestHandler):
    # same initialization but different implementation of the get() and post()

Thanks to @TimHoffman

Hope this will help somebody to apply some OO to their App Engine projects.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top