Django管理员在多对多字段中使用TabularInline的速度较慢

时间:2018-09-18 12:43:18

标签: django django-admin

我正在尝试使用Django admin在一个请求中可视化所有示例。它可以工作,但是确实很慢。我尝试在没有运气的情况下使用prefetchformsetraw_id_fieldsreadonly_fields。当我加载10个以上的样本时,它仍然非常慢。我在这里遇到N + 1问题。我检查了Django调试工具栏,并对该请求中的每个示例进行了查询。

这是我的模特:

# This is where the sample has all information
class Inventory(models.Model):
    sample_id = models.CharField(max_length=50, primary_key=True)

    def __str__(self):
        return '{0}'.format(self.sample_id)

# Intermediate model
class SampleRequestInventory(models.Model):
    sample = models.ForeignKey("Inventory", on_delete=models.CASCADE)
    request = models.ForeignKey("SampleRequest", on_delete=models.CASCADE)

# This is the request model that I'm looking  
class SampleRequest(models.Model):
    samples = models.ManyToManyField("Inventory", through="SampleRequestInventory")

这是我的django管理员配置:

class SamplesInline(admin.TabularInline):
    model = SampleRequestInventory
    # raw_id_fields = ('sample',)
    readonly_fields = ('sample',)
    extra = 0

# this formset did not work either
# class MyInlineFormset(BaseInlineFormSet):
#      def __init__(self, data=None, files=None, instance=None,
#              save_as_new=False, prefix=None, queryset=None, **kwargs):
#         super(MyInlineFormset, self).__init__(data, files, instance,
#                                           save_as_new, prefix, queryset, **kwargs)
#         self.queryset = SampleRequest.objects.all(). \
#         prefetch_related('samples')

class SampleRequestAdmin(admin.ModelAdmin):
    # This queryset for prefetching only makes an extra query...
    def get_queryset(self, request):
        qs = super(SampleRequestAdmin, self).get_queryset(request)
        return qs.prefetch_related('samples')
    # extra settings
    list_display = ('date', 'status',)
    ordering = ('date',)
    # inline that causes the slowness
    inlines = (SamplesInline, )
    # I tried using formset as well, but didn't work
    # formset = MyInlineFormset

1 个答案:

答案 0 :(得分:4)

尝试将以下内容添加到您的SamplesInline中:

def get_queryset(self, request): qs = super(SamplesInline, self).get_queryset(request) return qs.select_related('sample')

内联中的readonly_fields导致您的__str__类的额外查找满足Inventory