如何让Django在管理站点的外键上使用select_related()?

时间:2013-01-26 16:04:46

标签: django

我有几个型号:Review,其中包含专辑评论的字段,Record,这是专辑的名称等,而Band是乐队的名称。 Record有一个针对Band的外键,Review有一个针对Record的外键。

Review的管理表单中,我想显示所有Record的下拉列表选择框。目前,Record的unicode方法只是:

def __unicode__(self):
    return self.record_name

这不是很有用所以我把它改成了这个:

def __unicode__(self):
    return self.band.band_name + ' - ' + self.record_name  

现在为每个Record(3000左右)添加一个查询,显然不是很好。

阅读this answer,我尝试将其添加到Record的模型管理员中:

def queryset(self, request):
    return super(RecordAdmin, self).queryset(request).select_related('band')

但这没有任何区别。

是否可以在模型的__unicode__表示中使用外键字段而不会产生n平方查询?

更新:这是模型(删除了不相关的字段):

class Review(models.Model):

    def __unicode__(self):
        # this is used in other places where we show review titles
        return self.record.band.band_name + ' - ' + self.record.record_name

    record = models.ForeignKey('Record')
    review_text = models.TextField()

class Record(models.Model):

    def __unicode__(self):
        # this generates a billion queries
        #return self.record_name
        return self.band.band_name + ' - ' + self.record_name  

    def band_and_title(self):
        return self.band.band_name + ' - ' + self.record_name

    band = models.ForeignKey('Band')
    label = models.ForeignKey('Label')
    record_name = models.CharField(max_length=175)

class Band(models.Model):

    def __unicode__(self):
        return self.band_name

    band_name = models.CharField(max_length=100)

2 个答案:

答案 0 :(得分:1)

鉴于您的评论,您实际上可能需要选择相关的记录和频段。像这样:

class ReviewAdmin(admin.ModelAdmin):
    model = Review
    def queryset(self, request):
        return super(ReviewAdmin, self).queryset(request).select_related('record', 'record__band')

class RecordAdmin(admin.ModelAdmin):
    model = Record
    def queryset(self, request):
        return super(RecordAdmin, self).queryset(request).select_related('band')

使用Django Toolbar是发现正在运行的查询的好方法。

答案 1 :(得分:0)

您需要在管理网站创建更改表单时注入select_related。您可以通过覆盖ModelAdmin的ModelAdmin.formfield_for_foreignkey来执行此操作。像这样:

class ReviewAdmin(admin.ModelAdmin):
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "record":
            kwargs["queryset"] = Record.objects.all().select_related()

        return super(ReviewAdmin, self).formfield_for_foreignkey(
            db_field, request, **kwargs)