Django __unicode__ 和 FK 非常慢
如果我写类似的内容
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 子句中使用相同的参数,而不是智能地构建可以查找所有数据的查询。
如果我从 ChipStepping 和 ComponentType 的 unicode 函数中删除外键引用,这个问题就会减少。
如果 ComponentVendorProducts 中有足够的条目供我在管理页面中单击的供应商使用,则该页面可能需要几分钟的时间!
有没有办法可以减少管理页面上的数据库点击次数?
if I write something like
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")
And try to create an admin page for 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)
The resulting page can take upwards of 30 sec. to load
From some debugging I've done, I found that it repeatedly makes redundant singular queries for ChipStepping and then Chip, with the same argument in the where clause instead of intelligently building a query that can lookup all the data.
This problem is reduced if I remove the foreign key references from the unicode functions of ChipStepping and ComponentType
If there are enough entries in ComponentVendorProducts for a vendor I click on in the admin page, the page can take several minutes!
Is there a way I can reduce the number of database hits on the admin page?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的问题来自这样一个事实:每次您在
ComponentType
实例上调用__unicode__
时,Django 都会执行数据库调用。您的问题有两种解决方案:
ProductInline
的queryset
方法以包含select_lated('ChipStepping')
(Django 1.3 及更高版本) )。ComponentType
的默认管理器 (objects
)get_query_set
方法更改为让它包含select_lated
调用。Your problem comes from the fact that Django is doing a DB call everytime you call
__unicode__
on aComponentType
instance.You have two solutions to your issue:
ProductInline
'squeryset
method to includeselect_related('ChipStepping')
(Django 1.3 and superior).ComponentType
's default manager (objects
)get_query_set
method to have it include theselect_related
call.您可能还想查看此处给出的建议:
http://blog.ionelmc.ro/ 2012/01/19/tweaks-for-making-django-admin-faster/
似乎选择是针对每一行进行评估的,因此使用 formfield_for_dbfield 你可以按照链接中的建议缓存选项。这可以节省前往数据库渲染foreign_keys的每个下拉列表/选择框的时间
you might also want to checkout the suggestion given here:
http://blog.ionelmc.ro/2012/01/19/tweaks-for-making-django-admin-faster/
It seems that the choices are evaluated for every row, so using formfield_for_dbfield you can cache the choices as suggested in the link. This saves going to the db for rendering every single dropdown/select box for foreign_keys