mb52089
mb52089

Reputation: 872

django - checking to see if filter returns anything in the queryset

I'm a newb to Django. I need to check to see if a queryset returns any values at all, and if not, to skip to the next item in the loop. I tried try.. except ObjectDoesNotExist and that's not working. If a filter doesn't find anything, what does it return? How do I check for it?

Here's the existing code:

def assign_family_riders(leg):
    remaining_leg_riders = list(leg.riders.all())
    for car in CarAssignment.objects.filter(leg=leg):
        driver_family = car.driver.family
        try:
            riders = leg.riders.all().filter(family=driver_family)
        except ObjectDoesNotExist:
            continue
        for rider in riders:
            car.riders.add(rider)
            remaining_leg_riders.remove(rider)
    return remaining_leg_riders

Upvotes: 6

Views: 11780

Answers (4)

markwalker_
markwalker_

Reputation: 12869

The most efficient way to do this is to use exists() on the queryset before iterating over it or doing anything else that might perform a more intensive interaction with your database.

An example from the docs;

The most efficient method of finding whether a model with a unique field (e.g. primary_key) is a member of a QuerySet is:

entry = Entry.objects.get(pk=123)
if some_queryset.filter(pk=entry.pk).exists():
    print("Entry contained in queryset")

Which will be faster than the following which requires evaluating and iterating through the entire queryset:

if entry in some_queryset:
   print("Entry contained in QuerySet")

Upvotes: 1

locoboy
locoboy

Reputation: 38960

I'm pretty sure queryset returns nothing. You can probably check it using ./manage.py shell then see what is in riders.

Upvotes: 0

alan
alan

Reputation: 4852

As Timmy said in his answer, your loop will not be entered if the queryset returns nothing. On the other hand, if you really want to know the number of records a filter will return, you can call its count() method: CarAssignment.objects.filter(leg=leg).count() This performs a SELECT COUNT(*) for you in the background without retrieving any records.

See here for more information.

Upvotes: 2

Timmy O'Mahony
Timmy O'Mahony

Reputation: 53998

You don't need to specifically check. If the filter doesn't return any objects, an EmptyQuerySet will be returned and the forloop will never be entered.

riders = leg.riders.filter(family=driver_family)
for rider in riders:
    ...

If you really want to, you could simply do:

riders = leg.riders.filter(family=driver_family)
if riders:
    for rider in riders:
        ...

The ObjectDoesNotExist exception is only raised when you are trying to retrieve a particular record using get():

try:
     rider = leg.riders.get(...)
except Rider.DoesNotExist:
    ...

Upvotes: 12

Related Questions