Question

In web2py, suppose I have the following url:

www.example.com/customer/view/1

Which is backed by a view() function in the customer controller and displays the customer with id of 1 from a database.

In the view function I want to handle the following error cases:

  1. No argument is passed (/customer/view/) -> raise 404
  2. A non-integer argument is passed (/customer/view/apple) -> raise 404
  3. An integer argument is passed but does not exist in database (/customer/view/999999) -> raise 404
  4. An application error occurs such as cannot connect to database -> raise 500 exception

What is the standard/canonical/correct way to handle these cases in the controller function in way that returns the proper HTTP error? It's such a common scenario that I'd like to do it in a correct and succinct way every time.

This almost works except it doesn't distinguish between id not valid/existing errors and any other errors:

def view():
    try:
        customer = db(db.customer.id==request.args(0, cast=int)).select()[0]
    except:
        raise HTTP(404, 'Cannot find that customer')

    return dict(customer=customer)
Was it helpful?

Solution

def view():
    id = request.args(0, cast=int, otherwise=lambda: None)
    customer = db(db.customer.id == id).select().first()
    if not customer:
        raise HTTP(404, 'Cannot find that customer' if id
                   else 'Missing/invalid customer ID')
    return dict(customer=customer)

If the cast fails in request.args(), by default it will raise its own HTTP(404), but you won't have control over the message. So, you can instead use the otherwise argument to return None in that case. The database query will then return None if the arg is missing or a non-integer, or if the customer is not found in the database.

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