Leon
Leon

Reputation: 6544

IndexError, except doesnt work. Django

In views I have:

        def cars(request, cars_id):
            try:
                 car = Car.objects.filter(id=cars_id).values('model')
                 all_cars = Models.objects.filter(cars_id=cars_id).values('id', 
                 'name', 'cars_id')
            except Car.DoesNotExist:
                 cars_id=1
            except Exception, e:
                 print e
            except IndexError:
                 cars_id=1
            return render_to_response('cars.html', {'all_cars': all_cars, 'car':car[0]['model']})

So, in browser I enter, for example, car/10000000/, and I have an error:

IndexError: list index out of range.

Why my 'except' doesnt work and how to fix it?

Upvotes: 0

Views: 3023

Answers (4)

yedpodtrzitko
yedpodtrzitko

Reputation: 9359

1) learn about Exceptions hiearchy: If there's except block of Exception first and IndexError later, IndexError is never catched, because it's child class of Exception (see http://docs.python.org/library/exceptions.html#exception-hierarchy)

2) filter() never raises DoesNotExist exception, you have to check if there's some record in obtained QuerySet.

3) your problem is zero index in return line.

4) code should possibly looks like this:

def cars(request, cars_id):
    try:
        car = Car.objects.get(id=cars_id)
    except Car.DoesNotExist:
        #anyway - are you sure Car w/ id always exists?
        car = Car.objects.all()[:1] #get first car

    all_cars = Models.objects.filter(cars_id=cars_id).values('id', 'name', 'cars_id')
    return render_to_response('cars.html', {'all_cars': all_cars, 'car':car.model})

Upvotes: 0

Burhan Khalid
Burhan Khalid

Reputation: 174622

Your problem is in the last line car[0]['model']. When you don't have a car with the specified cars_id, the car list is empty, so you get an IndexError. The fix is to get a default car when the car requested doesn't exist - the default car is id = 1.

However, your all_cars is the same as your car line, except it contains extra fields. In other words, all_cars will have one car or zero cars when cars_id is invalid.

So its better to have all_cars be a listing of all cars in your database:

def cars(request, cars_id):
    all_cars = Models.objects.all().values('id',
               'name', 'cars_id')
    car = Car.objects.filter(id=cars_id).values('model')
    if not car:
        car = Car.objects.filter(id=1).values('model')
    return render_to_response('cars.html', {'all_cars': all_cars,
                                            'car':car[0]['model']})

Upvotes: 1

Thomas Kremmel
Thomas Kremmel

Reputation: 14783

I guess that your IndexError is thrown at an other location. For testing purposes try to wrap your entire view in a generic try catch block.

try:
    car = Car.objects.filter(id=cars_id).values('model')
    #include here all the other stuff you are doing
except Exception, e
     print e

Your view - rewrote:

def cars(request, cars_id):
        #to see whether you passed cars_id correctly
        print "cars_id is"
        print cars_id
        all_cars = Models.objects.filter(cars_id=cars_id).values('id', 
             'name', 'cars_id')
        try:
             car = Car.objects.get(id=cars_id).values('model') 
        except Car.DoesNotExist:
             print "the car for the given ID does not exist
        #just return the "entire" car object in the context of the response.
        #in the template you can then access car.model
        return render_to_response('cars.html', {'all_cars': all_cars, 'car':car})

Upvotes: 0

Serhii Holinei
Serhii Holinei

Reputation: 5864

If you want to catch object existence, I recomend you to use DoesNotExist exception

def cars(request, cars_id):
    try:
        car = Car.objects.get(id=cars_id).values('model')
    except Car.DoesNotExist:
        #other stuff

According to your updated question: you are trying to get first item of None. You should get car model for return in your try/except statement.

Upvotes: 2

Related Questions