tags:

views:

109

answers:

2

I'd like to reduce actual database hits when working in django so I've created this artificial example to outline the problem. The model looks like this:

class Car(models.Model):
    name = models.CharField(max_length=10)
    user = models.ForeignKey(User)

In my view I want to do something like this:

def cartest(request):
    cars = Car._default_manager.filter(user__username__exact='michael')[:5]
    first_car_name = cars[0].name
    another_car = cars[1]
    return HttpResponse(len(connection.queries))

So I want to select 5 entries from the database, do something with the first one, then do something with the second one (remember this is an artificial example). There must be some way to do this without hitting the database twice, right?

Thanks, Mike

+1  A: 

Are you actually running into performance issues at this point or are you just concerned about the future scalability of your application?

As Tim Wardle stated very well previously, don't try to prematurely optimize. Take advantage of the saved development time Django affords you to get your application out the door quicker. Once you have users, then take a look at your bottle necks are and attempt to fix them.

If, however, you are actually running into performance issues, I would take a look into the Queryset's ability to update multiple objects at once and to get data in bulk.

There is at least one rejected ticket I know of that might help you out (depending on your DB system).

You can always pull Django's ORM out and replace it with SQLAlchemy.

This post (possibly NSFW) has some pointers for making a high-performance Django application.

James Bennett has some good points about scaling in general, with some of that being about ORM performance.

John Paulett
Thanks, No performance issue... I just feel like 2 or 3 database hits when you need only need 1 is getting off on the wrong foot. Figured out how to get the desired effect, see comment above. Thanks, -Mike
Mike Bannister
+1  A: 

Ah, figured it out...this achieves the desired effect. Problem was subscripting the queryset rather than iterating over it (or calling list(queryset)). Only hits the database once:

def cartest(request):
    cars = list(Car._default_manager.filter(user__username__exact='michael')[:5])
    first_car_name = car[0]
    another_car = car[1]
    return HttpResponse(len(connection.queries))
Mike Bannister
An easier way to achieve the same effect is simply to do `cars = list(Car._default_manager.filter(user__username__exact='michael')[:5])` - calling `list` on a queryset evaluates it.
Daniel Roseman
Perfect. Updating my answer. Thank you.
Mike Bannister