Django __unicode__和FK非常慢

mat*_*657 2 python sql django performance admin

如果我写的东西像

class Chip(models.Model):
  name      = models.CharField(max_length=16)
  shortname = models.CharField(primary_key=True, unique=True, max_length = 16)

  def __unicode__(self):
    return self.shortname

class ChipStepping(models.Model):

  stepping = models.CharField (max_length=16)
  ChipShortname = models.ForeignKey('Chip', db_column="ChipShortname")

  def __unicode__(self):
    return "%s:%s" % (self.ChipShortname, self.stepping)

class ComponentType(models.Model):
  name         = models.CharField (max_length=32)
  ChipStepping = models.ForeignKey('ChipStepping', db_column="ChipStepping")

  def __unicode__(self):
    return "%s(%s)" % (self.name, self.ChipStepping);

class ComponentVendor(models.Model):
  name     = models.CharField      (unique=True, max_length=16)
  products = models.ManyToManyField('ComponentType', through='ComponentVendorProduct', related_name='vendors')

  def __unicode__(self):
    return "%s" % (self.name)

class ComponentVendorProduct(models.Model):
  ComponentVendor = models.ForeignKey('ComponentVendor', db_column="ComponentVendor")
  ComponentType   = models.ForeignKey('ComponentType'  , db_column="ComponentType")
Run Code Online (Sandbox Code Playgroud)

并尝试为ComponentVendor创建一个管理页面

class ProductInline(admin.TabularInline):
  model = ComponentVendor.products.through
  extra = 0

class ComponentVendorAdmin(admin.ModelAdmin):
  inlines = [ProductInline]
  list_filter = ['products__name']
  exclude = ['products']

admin.site.register(ComponentVendor, ComponentVendorAdmin)
Run Code Online (Sandbox Code Playgroud)

生成的页面最多可能需要30秒.加载从我做过的一些调试中,我发现它反复为ChipStepping和Chip创建冗余的单一查询,在where子句中使用相同的参数,而不是智能地构建可以查找所有数据的查询.

如果我从ChipStepping和ComponentType 的unicode函数中删除外键引用,则会减少此问题

如果ComponentVendorProducts中有足够的条目供我在管理页面中单击的供应商,该页面可能需要几分钟!

有没有办法可以减少管理页面上的数据库命中数?

Tho*_*zco 6

你的问题来自于一个事实,即Django是做你调用一个DB每次调用__unicode__上一个ComponentType实例.

您有两个问题的解决方案:

  1. 你覆盖你ProductInlinequeryset方法包括select_related('ChipStepping')(Django 1.3和上级).
  2. 或者,如果您想在其他地方解决问题,您可能希望更改ComponentType默认的manager(objects)get_query_set方法以使其包含该select_related调用.

  • 谢谢!我在这里找到了相关文档https://docs.djangoproject.com/en/dev/topics/db/managers/ (2认同)