django 管理和内联:使用 'through' 模型的多对多 - 性能问题
django admin and inlines: many-to-many with 'through' model - performance issue
我对使用中间模型 ('through') 与管理员和内联的 m2m 字段有疑问。这是代码:
# MODELS
class Engagement(models.Model):
parent_engagement = models.ForeignKey('self', blank=True, null=True, related_name='child_engagements')
title = models.CharField('Engagement title', max_length=200)
...
# client
client = models.ForeignKey(Client, related_name='engagements')
primary_point_of_contact = models.ForeignKey(
ClientContact, null=True, blank=True,
related_name='engagements_for_which_point_of_contact'
)
additional_point_of_contacts = models.ManyToManyField(
ClientContact,
through='AdditionalPointOfContact'
)
.... # other fields
class ClientContact(models.Model):
first_name = models.CharField(max_length=200, blank=True)
last_name = models.CharField(max_length=200, blank=True)
jobtitle = models.CharField(max_length=200, blank=True)
company = models.ForeignKey(Client, null=True, blank=True)
class AdditionalPointOfContact(models.Model):
engagement = models.ForeignKey("Engagement", related_name='additional_points_of_contact')
client_contact = models.ForeignKey("ClientContact")
description = models.CharField(max_length=500, blank=True)
def __unicode__(self):
return self.client_contact.__unicode__()
# ADMIN
class EngagementAdmin(ChaosDefaultAdmin):
....
inlines = [
ScopeServiceElementAdmin,
AdditionalPointOfContactInlineAdmin
]
list_display = (...
class AdditionalPointOfContactInlineAdmin(admin.TabularInline):
model = AdditionalPointOfContact
fieldsets = [
('', {
'fields': (('client_contact',),
('description',),)
}),
]
extra = 0
min_num = 0
根据 django-debug-toolbar
,sql 选项卡显示 8382 个查询,而注释掉 AdditionalPointOfContactInlineAdmin
它减少到 10 个查询,所以那里有问题。
我可能会覆盖 AdditionalPointOfContactInlineAdmin
的 get_queryset 方法,但我不知道具体如何以及为什么。有什么建议吗?
尝试覆盖 EngagementAdmin.get_queryset():
class EngagementAdmin(ChaosDefaultAdmin):
def get_queryset(self, request):
qs = super(EngagementAdmin, self).get_queryset(request)
return qs.prefetch_related('additional_points_of_contact')
# or
# return qs.prefetch_related('additional_points_of_contact__client_contact')
我对使用中间模型 ('through') 与管理员和内联的 m2m 字段有疑问。这是代码:
# MODELS
class Engagement(models.Model):
parent_engagement = models.ForeignKey('self', blank=True, null=True, related_name='child_engagements')
title = models.CharField('Engagement title', max_length=200)
...
# client
client = models.ForeignKey(Client, related_name='engagements')
primary_point_of_contact = models.ForeignKey(
ClientContact, null=True, blank=True,
related_name='engagements_for_which_point_of_contact'
)
additional_point_of_contacts = models.ManyToManyField(
ClientContact,
through='AdditionalPointOfContact'
)
.... # other fields
class ClientContact(models.Model):
first_name = models.CharField(max_length=200, blank=True)
last_name = models.CharField(max_length=200, blank=True)
jobtitle = models.CharField(max_length=200, blank=True)
company = models.ForeignKey(Client, null=True, blank=True)
class AdditionalPointOfContact(models.Model):
engagement = models.ForeignKey("Engagement", related_name='additional_points_of_contact')
client_contact = models.ForeignKey("ClientContact")
description = models.CharField(max_length=500, blank=True)
def __unicode__(self):
return self.client_contact.__unicode__()
# ADMIN
class EngagementAdmin(ChaosDefaultAdmin):
....
inlines = [
ScopeServiceElementAdmin,
AdditionalPointOfContactInlineAdmin
]
list_display = (...
class AdditionalPointOfContactInlineAdmin(admin.TabularInline):
model = AdditionalPointOfContact
fieldsets = [
('', {
'fields': (('client_contact',),
('description',),)
}),
]
extra = 0
min_num = 0
根据 django-debug-toolbar
,sql 选项卡显示 8382 个查询,而注释掉 AdditionalPointOfContactInlineAdmin
它减少到 10 个查询,所以那里有问题。
我可能会覆盖 AdditionalPointOfContactInlineAdmin
的 get_queryset 方法,但我不知道具体如何以及为什么。有什么建议吗?
尝试覆盖 EngagementAdmin.get_queryset():
class EngagementAdmin(ChaosDefaultAdmin):
def get_queryset(self, request):
qs = super(EngagementAdmin, self).get_queryset(request)
return qs.prefetch_related('additional_points_of_contact')
# or
# return qs.prefetch_related('additional_points_of_contact__client_contact')