Django error: list index out of range (when there's no objects)

Question:

Everything works fine until I delete all the objects and try to trigger the url, then it gives me this traceback: list index out of range. I can’t use get because there might be more than one object and using [0] with filter leads me to this error when there’s no object present, any way around this? I’m trying to get the recently created object of the Ticket model (if created that is) and then perform the logic, so that if the customer doesn’t have any tickets, nothing happens but if the customer does then the logic happens

Models

class Ticket(models.Model):
    date_posted = models.DateField(auto_now_add=True, blank=True, null=True)
    customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)

Views

try:
    ticket = Ticket.objects.filter(customer=customer).order_by("-id")[0]
    now = datetime.now().date()
    set_date = ticket.date_posted
    check_time = now - set_date <= timedelta(hours=24)
    if check_time:
        print('working')
    else:
        print('not working')
except Ticket.DoesNotExist:
    ticket = None

context = {"check_time": check_time}
Asked By: betty_

||

Answers:

Instead of getting the list of tickets and accessing the first element in one line, you should first get the list, then check it’s not empty, and then get the first element.

Answered By: Daniel Robinson

Instead of this:

ticket = Ticket.objects.filter(customer=customer).order_by("-id")[0]

Use this using exists() which is a very efficient way if there is any object exist in DB:

tickets = Ticket.objects.filter(customer=customer).order_by("-id")
if tickets.exists():
   ticket = tickets.first()
else:
   ticket = None

Update

You can do the query inside the filter function.

tickets = Ticket.objects.filter(customer=customer, date_posted__lte=timezone.now().date() - timedelta(hours=24))

context = {"check_time": tickets.exists()}
Answered By: ruddra

You can also do this:

ticket = Ticket.objects.filter(customer=customer).order_by("-id").first() or None

instead of:

ticket = Ticket.objects.filter(customer=customer).order_by("-id")[0]
Answered By: Osman
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.