Джанго __unicode__ и FK очень медленно - PullRequest
2 голосов
/ 13 февраля 2012

если я напишу что-то вроде

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")

и попытаюсь создать страницу администратора для 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)

Результирующая страница может занять более 30 секунд.загрузить После некоторой отладки, которую я сделал, я обнаружил, что она неоднократно выполняет избыточные единичные запросы для ChipStepping, а затем для Chip, с тем же аргументом в предложении where вместо интеллектуального построения запроса, который может искать все данные.

Эта проблема уменьшается, если я удаляю ссылки на внешние ключи из функций unicode ChipStepping и ComponentType

Если в ComponentVendorProducts достаточно записей для поставщика, на которого я нажимаю на странице администратора, страница может занять несколько минут!

Есть ли способ уменьшить количество обращений к базе данных на странице администратора?

Ответы [ 2 ]

6 голосов
/ 13 февраля 2012

Ваша проблема связана с тем, что Django выполняет вызов БД каждый раз, когда вы вызываете __unicode__ в экземпляре ComponentType.

У вас есть два решения вашей проблемы:

  1. Вы переопределяете свой метод ProductInline queryset, чтобы включить select_related('ChipStepping') (Django 1.3 и выше).
  2. В качестве альтернативы, если вы хотите решить проблему и в другом месте, вы можете изменить метод управления ComponentType по умолчанию (objects) get_query_set, чтобы он включал в себя вызов select_related.
0 голосов
/ 09 ноября 2012

Вы также можете воспользоваться предложением, приведенным здесь: http://blog.ionelmc.ro/2012/01/19/tweaks-for-making-django-admin-faster/

Кажется, что варианты оцениваются для каждой строки, поэтому с помощью formfield_for_dbfield вы можете кэшировать варианты, как предложено в ссылке. Это спасает переход к БД для рендеринга каждого выпадающего / выбранного поля для Foreign_keys

...