views:

89

answers:

3

Hi

Disclaimer: completely new to Python from a PHP background

Ok I'm using Python on Google App Engine with Google's webapp framework.

I have a function which I import as it contains things which need to be processed on each page.

def some_function(self):
    if data['user'].new_user and not self.request.path == '/main/new':
        self.redirect('/main/new')

This works fine when I call it, but how can I make sure the app is killed off after the redirection. I don't want anything else processing. For example I will do this:

class Dashboard(webapp.RequestHandler):
    def get(self):
        some_function(self)
        #Continue with normal code here
        self.response.out.write('Some output here')

I want to make sure that once the redirection is made in some_function() (which works fine), that no processing is done in the get() function following the redirection, nor is the "Some output here" outputted.

What should I be looking at to make this all work properly? I can't just exit the script because the webapp framework needs to run.

I realise that more than likely I'm just doing things in completely the wrong way any way for a Python app, so any guidance would be a great help. Hopefully I have explained myself properly and someone will be able to point me in the right direction.

Thanks

+4  A: 

I suggest you return a boolean from some_function() based on whether the caller should continue execution or not. Example:

def some_function(self):
    if data['user'].new_user and not self.request.path == '/main/new':
        self.redirect('/main/new')
        return True
    return False

class Dashboard(webapp.RequestHandler):
    def get(self):
        if some_function(self):
            return
        #Continue with normal code here
        self.response.out.write('Some output here')

There's also a slightly more complicated alternative that might be helpful if some_function() is nested several levels deep, or if you may have many functions like this. The idea: raise an exception indicating that you want processing to stop, and use a subclass of webapp.RequestHandler which simply catches and ignores this exception. Here's a rough idea of how this might go:

class RedirectException(Exception):
    """Raise this from any method on a MyRequestHandler object to redirect immediately."""
    def __init__(self, uri, permanent=False):
        self.uri = uri
        self.permanent = permanent

class RedirectRequestHandler(webapp.RequestHandler):
    def handle_exception(self, exception, debug_mode):
        if isinstance(exception, RedirectException):
            self.redirect(exception.uri, exception.permanent)
        else:
            super(MyRequestHandler, self).handle_exception(exception, debug_mode)

This might make it a little easier to work with some_function() (and make your other request handlers a bit easier to read). For example:

def some_function(self):
    if data['user'].new_user and not self.request.path == '/main/new':
        raise RedirectException('/main/new')

class Dashboard(RedirectRequestHandler):
     # rest of the implementation is the same ...
David Underhill
Two great solutions, the second one opening my mind a bit with my learning progress. Returning a boolean was how I've been doing it but you've gone and neatened it up a bit for me - thanks very much for your response.
Mike Hayes
To be honest I'm only just getting my head around the exception raising now 10 minutes later, it's starting to become more clear but I think it's still going over my head. I'll look into it, thanks a lot though.
Mike Hayes
The boolean approach is certainly simpler, and should suffice for simple cases (like the one you present in your question). Just keep the exception approach in your back pocket and consider it when you the boolean scheme gets trickier (e.g., nested functions or lots of functions like `some_function()`).
David Underhill
+4  A: 

How about this?

class Dashboard(webapp.RequestHandler):
    def some_function(self):
        if data['user'].new_user and not self.request.path == '/main/new':
            self.redirect('/main/new')
            return True
        else:
            return False
    def get(self):
        if not self.some_function():
            self.response.out.write('Some output here')

For reference, if you're going to need some_function() in a lot of RequestHandlers it would be pythonic to make a class that your other RequestHandlers can subclass from:

class BaseHandler(webapp.RequestHandler):
    def some_function(self):
        if data['user'].new_user and not self.request.path == '/main/new':
            self.redirect('/main/new')
            return False
        else:
            return True

class Dashboard(BaseHandler):
    def get(self):
        if not self.some_function():
            self.response.out.write('Some output here')
Dan McDougall
Good minds think alike? :)
David Underhill
As I commented on the other answer, I have been returning a boolean but you have made it a bit cleaner for me plus just generally opened up my mind a bit.I like your thoughts on setting up a class which the RequestHandlers can subclass from, I will be doing this :) Thanks for pointing me in the right direction of being a true Python head. 6 years experience I've had in PHP... only a few days in Python, so much to learn!
Mike Hayes
I'm new to StackOverflow, this was the answer marked as accepted because I will be using both the boolean part and the second recommendation on how to be more "pythonic" :) Thanks very much to both of you though.
Mike Hayes
A: 

I know this question is quite old but I was doing something today and naturally tried another solution without thinking about it, it has worked fine but I'm wondering if there would be a problem with doing it this way.

My solution now is just to return, return anything actually but I use "return False" in that there is a problem with the request as it is so I'm printing an error or redirecting elsewhere.

By returning I've already set the output etc and I'm killing off the get() or post() function early.

Is this an ok solution?

Mike Hayes