user168983
user168983

Reputation: 844

Avoiding multiple queries to display model data on Django admin

I am using Django amdin for one of my data models. I want to display customized values on admin UI for each model. On db, the result of a single query runs as multiple queries on django admin, one for each row I am trying to avoid that.

Here are my models:

class words(models.Model):
    word_id=models.AutoField(primary_key=True)
    word=models.CharField(max_length=200,unique=True)
    def __unicode__(self):
        return '%s - %s' % (self.word,self.word_id)

class meanings(models.Model):
    id=models.AutoField(primary_key=True)
    word_id=models.ForeignKey(words,on_delete=models.CASCADE,db_column='word_id')
    meaning=models.CharField(max_length=200)
    def __unicode__(self):
        return '%s  %s  %d ' % ( self.spelling_id.spelling,self.meaning,self.id)

For the second model, while loading the page, for each row I saw there are 2 queries running one on words table and other on meanings table. (from debug toolbar)

I tried avoiding that by using the below option.

models.py:

class meanings(models.Model):
    meaning_id=models.AutoField(primary_key=True)
    word_id=models.ForeignKey(words,on_delete=models.CASCADE,db_column='word_id')
    meaning=models.CharField(max_length=200)

admin.py:

def modified_output(self):
        cursor = connection.cursor()
        cursor.execute("select word,meaning,id from meanings a,words b where a.word_id=b.word_id and meaning_id= "+str(self.id))
        row = dictfetchall(cursor)
        a=unicode(row[0]['word'])
        b=unicode(row[0]['meaning'])
        d=(row[0]['id'])
        return '%s  %s  %d ' % ( a,b,d)


meanings.add_to_class("__str__", modified_output)

Now for each row there is only 1 query running. But as the dependency on models have more than 2 tables in join of a query, it will still consume time. So my question is instead of running 1 query for each row, can we have the query result displayed directly for each page.

for example result of the following query on a page:

select * from table ;

instead of

select * from table when id=1;
select * from table when id=2;
.
.
.

Any help is greatly appreciated.Thanks

Upvotes: 1

Views: 1369

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599490

You should use the list_select_related option on the ModelAdmin to tell Django to do a JOIN query.

class MeaningAdmin(admin.ModelAdmin):
    list_select_related = ('word_id',)

(Note, you really shouldn't call your FK fields things like word_id. The field gives access to an actual instance of Word, so it should just be called word; the underlying db column will automatically be called word_id.)

Upvotes: 2

Related Questions