views:

139

answers:

3

I'm trying to optimize the database calls coming from a fairly small Django app. At current I have a couple of models, Inquiry and InquiryStatus. When selecting all of the records from MySQL, I get a nice JOIN statement on the two tables, followed by many requests to the InquiryStatus table. Why is Django still making individual requests if I've already done a select_related()?

The models look like so:

class InquiryStatus(models.Model):
    status = models.CharField(max_length=25) 
    status_short = models.CharField(max_length=5)
    class Meta:
        ordering = ["-default_status", "status", "status_short"]

class Inquiry(models.Model):
    ts = models.DateTimeField(auto_now_add=True)
    type = models.CharField(max_length=50) 
    status = models.ForeignKey(InquiryStatus)
    class Meta:
        ordering = ["-ts"]

The view I threw together for debugging looks like so:

def inquiries_list(request, template_name="inquiries/list_inquiries.js"):
    ## Notice the "print" on the following line.  Forces evaluation.
    print models.Inquiry.objects.select_related('status').all()
    return HttpResponse("CRAPSTICKS")

I've tried using select_related(depth=1), with no change. Each of the extraneous requests to the database are selecting one specific id in the WHERE clause.

Update:

So there was one bit of very important code which should have been put in with the models:

from fullhistory import register_model
register_model(Inquiry)
register_model(InquiryStatus)

As a result, fullhistory was (for reasons I cannot fathom) pulling each individual result and parsing it.

A: 

I believe this has to do with lazy evaluation. Django only hits the DB if and when necessary, not when you invoke models.Inquiry.objects.select_related('status').all()

http://docs.djangoproject.com/en/dev/topics/db/queries/#id3

Gabriel Ross
Actually, if you look at the line where I have the query, it is a `print` line. As a result, it is evaluated and generates a ton of queries.
Jack M.
A: 

The code you've shown shouldn't actually generate any queries at all - QuerySets are only evaluated when necessary, not when they're defined, and you don't use the value anywhere so the execution won't be done.

Please show us a template or some other code that actually evaluates the qs - slices it, iterates, prints, or anything.

Daniel Roseman
Actually, if you look at the line where I have the query, it is a `print` line. As a result, it is evaluated and generates a ton of queries.
Jack M.
A: 

It seems that fullhistory ends up serializing the object, which evaluates each field in the instance to give it a base to compare to.

Take a look at the get_all_data function:

http://code.google.com/p/fullhistory/source/browse/trunk/fullhistory/fullhistory.py

If anybody wants to write up a detailed reason why this happens, I'll gladly mark that answer correct.

Jack M.