Django Admin外键从单个SQL查询下拉

时间:2013-09-18 07:27:58

标签: mysql django-models django-forms

是否有一种简单的方法可以让Django使用单个SQL查询填充外键的下拉列表?

考虑以下模型;

class Site(models.Model):
    code = models.CharField(max_length=5)
    name = models.CharField(max_length=45)

    def __unicode__(self):
        return u'%s - %s' % (self.code, self.name)

class Location(models.Model):
    site = models.ForeignKey(Site)
    name = models.CharField(max_length=45, verbose_name='Location Name')

    def __unicode__(self):
        return u'%s - %s' % (self.site, self.name)

其他模型则包含models.ForeignKey(Location),并选择这些模型以admin.ModelAdmin形式呈现为下拉列表。

使用django-debug-toolbar我可以看到在填充下拉列表时,我为每个具有site_id值的Location项执行了以下查询;

SELECT 
  `myApp_site`.`id`, 
  `myApp_site`.`code`, 
  `myApp_site`.`name` 
FROM `myApp_site` 
WHERE `myApp_site`.`id` = 1

我可以看到这是因为我在self.site中使用def __unicode__(self),因为我想查看每个位置的网站。

我尝试在list_select_related = True中使用admin.ModelAdmin,但这仅适用于实例上的相关数据,而不适用于表单中的可能值。

通常,整个外键下拉列表可以从单个查询填充,如;

SELECT 
  `myApp_location`.`id`, 
  `myApp_location`.`name`,
  `myApp_site`.`code`, 
  `myApp_site`.`name` 
FROM `myApp_site`
INNER JOIN `myApp_site` ON (`myApp_location`.`site_id` = `myApp_site`.`id`)

我可以强制使用位置模型select_related()并消除查询吗?

有没有更好的方法来包含网站的位置或减少Django正在执行的查询数量?

我是否陷入了Django反模式?我有几个像这样的外键字段,我担心随着数据库的填满,查询的数量会增加。

1 个答案:

答案 0 :(得分:0)

尝试在AdminClass上使用formfield_for_foreignkey方法,在那里你可以覆盖ForeignKey的查询集。见下面的例子

def formfield_for_foreignkey(self, db_field, request, **kwargs):
    if db_field.name == 'location':
        kwargs["queryset"] = Location.objects.select_related('site').all()
    return super(ModelWithLocationAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)