How do you call a handler from your basehandler in

2020-08-01 02:15发布

问题:

I'd like to do something like this:

class Basehandler(webapp.RequestHandler):

  def __init__(self):
    if checkforspecialcase: #check something that always needs to be handled
      return SpecialCaseHandler.get()

class NormalHandler(Basehandler):

  def get(self):
    print 'hello world'
    return

class SpecialCaseHandler(Basehandler):

  def get(self):
    print 'hello special world'
    return

The idea is that no matter what handler is initially called, if a certain case is met, we basically switch to another handler.

I'm pretty new to python, so I'm not sure whether what I'm trying to do is possible. Or whether this is the best approach. What I'm really trying to do is make sure to show someone the complete-your-profile page if they've started the registration process but haven't completed it... no matter what request they're making. So the "checkforspecialcase" looks at their sessions and checks for incomplete info.

回答1:

To keep things DRY, use the Template Method pattern

class BaseHandler(webapp.RequestHandler):
    def DoGet(self, *args):
        ''' defined in derived classes, actual per-handler get() logic'''
        pass

    def get(self, *args):
        # don't get caught in endless redirects!
        if specialCase and not self.request.path.startswith('/special'):
            self.redirect('/special')
        else:
            self.DoGet(*args)

class NormalHandler(BaseHandler):
    def DoGet(self, *args):
        # normal stuff

class SpecialHandler(BaseHandler):
    def DoGet(self, *args):
        # SPECIAL stuff


回答2:

WSGIApplication routes incoming requests based on the URL. For example,

application = webapp.WSGIApplication(
              [('/special-case', SpecialCaseHandler)])

When checkforspecialcase passes, you can use self.redirect('/special-case').



回答3:

Your Basehandler could just implement a get() that checks for the special case and either redirects or calls self.view(), and each handler could implement view() (or whatever you'd like to call it) rather than get().

I'm not really into writing a class for each of my handlers, or using inheritance so conspicuously, so I'd recommend rolling decorators like these:

routes = []

def get (route):
    def makeHandler (handle, *args, **kwargs):
        class Handler (webapp.RequestHandler):
            def get (self, *args, **kwargs):
                shouldRedirectToCompleteProfile = # do your test
                if shouldRedirectToCompleteProfile:
                    self.redirect('/special-case')
                else:
                    handle(self, *args, **kwargs)
        routes.append((route, Handler))
        return Handler
    return makeHandler

def post (route):
    def makeHandler (handle, *args, **kwargs):
        class Handler (webapp.RequestHandler):
            def post (self, *args, **kwargs):
                handle(self, *args, **kwargs)
        routes.append((route, Handler))
        return Handler
    return makeHandler

@get('/')
def home (ctx):
    # <...>

@get('/whatever/(.*)/(.*)')
def whatever (ctx, whatever0, whatever1):
    # <...>

@post('/submit')
def submit (ctx):
    # <...>

application = webapp.WSGIApplication(routes)