Eliminated queries for distinct related object counts for better performance

This commit is contained in:
Jeremy Stretch 2018-02-02 17:46:23 -05:00
parent 835d13542f
commit d25d8c21f6
5 changed files with 63 additions and 32 deletions

View File

@ -65,6 +65,10 @@ RACK_ROLE = """
{% endif %} {% endif %}
""" """
RACK_DEVICE_COUNT = """
<a href="{% url 'dcim:device_list' %}?rack_id={{ record.pk }}">{{ value }}</a>
"""
RACKRESERVATION_ACTIONS = """ RACKRESERVATION_ACTIONS = """
{% if perms.dcim.change_rackreservation %} {% if perms.dcim.change_rackreservation %}
<a href="{% url 'dcim:rackreservation_edit' pk=record.pk %}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a> <a href="{% url 'dcim:rackreservation_edit' pk=record.pk %}" class="btn btn-xs btn-warning"><i class="glyphicon glyphicon-pencil" aria-hidden="true"></i></a>
@ -83,6 +87,14 @@ MANUFACTURER_ACTIONS = """
{% endif %} {% endif %}
""" """
DEVICEROLE_DEVICE_COUNT = """
<a href="{% url 'dcim:device_list' %}?role={{ record.slug }}">{{ value }}</a>
"""
DEVICEROLE_VM_COUNT = """
<a href="{% url 'virtualization:virtualmachine_list' %}?role={{ record.slug }}">{{ value }}</a>
"""
PLATFORM_DEVICE_COUNT = """ PLATFORM_DEVICE_COUNT = """
<a href="{% url 'dcim:device_list' %}?platform={{ record.slug }}">{{ value }}</a> <a href="{% url 'dcim:device_list' %}?platform={{ record.slug }}">{{ value }}</a>
""" """
@ -226,12 +238,16 @@ class RackTable(BaseTable):
class RackDetailTable(RackTable): class RackDetailTable(RackTable):
devices = tables.Column(accessor=Accessor('device_count')) device_count = tables.TemplateColumn(
template_code=RACK_DEVICE_COUNT,
verbose_name='Devices'
)
get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization') get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization')
class Meta(RackTable.Meta): class Meta(RackTable.Meta):
fields = ( fields = (
'pk', 'name', 'site', 'group', 'facility_id', 'tenant', 'role', 'u_height', 'devices', 'get_utilization' 'pk', 'name', 'site', 'group', 'facility_id', 'tenant', 'role', 'u_height', 'device_count',
'get_utilization',
) )
@ -370,12 +386,25 @@ class DeviceBayTemplateTable(BaseTable):
class DeviceRoleTable(BaseTable): class DeviceRoleTable(BaseTable):
pk = ToggleColumn() pk = ToggleColumn()
name = tables.LinkColumn(verbose_name='Name') name = tables.LinkColumn(verbose_name='Name')
device_count = tables.Column(verbose_name='Devices') device_count = tables.TemplateColumn(
vm_count = tables.Column(verbose_name='VMs') template_code=DEVICEROLE_DEVICE_COUNT,
accessor=Accessor('devices.count'),
orderable=False,
verbose_name='Devices'
)
vm_count = tables.TemplateColumn(
template_code=DEVICEROLE_VM_COUNT,
accessor=Accessor('virtual_machines.count'),
orderable=False,
verbose_name='VMs'
)
color = tables.TemplateColumn(COLOR_LABEL, verbose_name='Label') color = tables.TemplateColumn(COLOR_LABEL, verbose_name='Label')
slug = tables.Column(verbose_name='Slug') slug = tables.Column(verbose_name='Slug')
actions = tables.TemplateColumn(template_code=DEVICEROLE_ACTIONS, attrs={'td': {'class': 'text-right'}}, actions = tables.TemplateColumn(
verbose_name='') template_code=DEVICEROLE_ACTIONS,
attrs={'td': {'class': 'text-right'}},
verbose_name=''
)
class Meta(BaseTable.Meta): class Meta(BaseTable.Meta):
model = DeviceRole model = DeviceRole
@ -388,8 +417,18 @@ class DeviceRoleTable(BaseTable):
class PlatformTable(BaseTable): class PlatformTable(BaseTable):
pk = ToggleColumn() pk = ToggleColumn()
device_count = tables.TemplateColumn(template_code=PLATFORM_DEVICE_COUNT, verbose_name='Devices') device_count = tables.TemplateColumn(
vm_count = tables.TemplateColumn(template_code=PLATFORM_VM_COUNT, verbose_name='VMs') template_code=PLATFORM_DEVICE_COUNT,
accessor=Accessor('devices.count'),
orderable=False,
verbose_name='Devices'
)
vm_count = tables.TemplateColumn(
template_code=PLATFORM_VM_COUNT,
accessor=Accessor('virtual_machines.count'),
orderable=False,
verbose_name='VMs'
)
actions = tables.TemplateColumn( actions = tables.TemplateColumn(
template_code=PLATFORM_ACTIONS, template_code=PLATFORM_ACTIONS,
attrs={'td': {'class': 'text-right'}}, attrs={'td': {'class': 'text-right'}},

View File

@ -276,7 +276,7 @@ class RackListView(ObjectListView):
).prefetch_related( ).prefetch_related(
'devices__device_type' 'devices__device_type'
).annotate( ).annotate(
device_count=Count('devices', distinct=True) device_count=Count('devices')
) )
filter = filters.RackFilter filter = filters.RackFilter
filter_form = forms.RackFilterForm filter_form = forms.RackFilterForm
@ -715,10 +715,7 @@ class DeviceBayTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# #
class DeviceRoleListView(ObjectListView): class DeviceRoleListView(ObjectListView):
queryset = DeviceRole.objects.annotate( queryset = DeviceRole.objects.all()
device_count=Count('devices', distinct=True),
vm_count=Count('virtual_machines', distinct=True)
)
table = tables.DeviceRoleTable table = tables.DeviceRoleTable
template_name = 'dcim/devicerole_list.html' template_name = 'dcim/devicerole_list.html'
@ -756,10 +753,7 @@ class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# #
class PlatformListView(ObjectListView): class PlatformListView(ObjectListView):
queryset = Platform.objects.annotate( queryset = Platform.objects.all()
device_count=Count('devices', distinct=True),
vm_count=Count('virtual_machines', distinct=True)
)
table = tables.PlatformTable table = tables.PlatformTable
template_name = 'dcim/platform_list.html' template_name = 'dcim/platform_list.html'

View File

@ -196,14 +196,6 @@ class Role(models.Model):
self.weight, self.weight,
) )
@property
def count_prefixes(self):
return self.prefixes.count()
@property
def count_vlans(self):
return self.vlans.count()
@python_2_unicode_compatible @python_2_unicode_compatible
class Prefix(CreatedUpdatedModel, CustomFieldModel): class Prefix(CreatedUpdatedModel, CustomFieldModel):

View File

@ -228,9 +228,18 @@ class AggregateDetailTable(AggregateTable):
class RoleTable(BaseTable): class RoleTable(BaseTable):
pk = ToggleColumn() pk = ToggleColumn()
prefix_count = tables.TemplateColumn(accessor=Accessor('count_prefixes'), template_code=ROLE_PREFIX_COUNT, orderable=False, verbose_name='Prefixes') prefix_count = tables.TemplateColumn(
vlan_count = tables.TemplateColumn(accessor=Accessor('count_vlans'), template_code=ROLE_VLAN_COUNT, orderable=False, verbose_name='VLANs') accessor=Accessor('prefixes.count'),
slug = tables.Column(verbose_name='Slug') template_code=ROLE_PREFIX_COUNT,
orderable=False,
verbose_name='Prefixes'
)
vlan_count = tables.TemplateColumn(
accessor=Accessor('vlans.count'),
template_code=ROLE_VLAN_COUNT,
orderable=False,
verbose_name='VLANs'
)
actions = tables.TemplateColumn(template_code=ROLE_ACTIONS, attrs={'td': {'class': 'text-right'}}, verbose_name='') actions = tables.TemplateColumn(template_code=ROLE_ACTIONS, attrs={'td': {'class': 'text-right'}}, verbose_name='')
class Meta(BaseTable.Meta): class Meta(BaseTable.Meta):

View File

@ -159,10 +159,7 @@ class ClusterBulkEditView(PermissionRequiredMixin, BulkEditView):
class ClusterBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class ClusterBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'virtualization.delete_cluster' permission_required = 'virtualization.delete_cluster'
cls = Cluster cls = Cluster
queryset = Cluster.objects.annotate( queryset = Cluster.objects.all()
device_count=Count('devices', distinct=True),
vm_count=Count('virtual_machines', distinct=True)
)
table = tables.ClusterTable table = tables.ClusterTable
default_return_url = 'virtualization:cluster_list' default_return_url = 'virtualization:cluster_list'