mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Closes #10197: Add a cached counter field for virtual chassis members
This commit is contained in:
@ -1156,13 +1156,15 @@ class CablePathSerializer(serializers.ModelSerializer):
|
||||
class VirtualChassisSerializer(NetBoxModelSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:virtualchassis-detail')
|
||||
master = NestedDeviceSerializer(required=False, allow_null=True, default=None)
|
||||
|
||||
# Counter fields
|
||||
member_count = serializers.IntegerField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = VirtualChassis
|
||||
fields = [
|
||||
'id', 'url', 'display', 'name', 'domain', 'master', 'description', 'comments', 'tags', 'custom_fields',
|
||||
'member_count', 'created', 'last_updated',
|
||||
'created', 'last_updated', 'member_count',
|
||||
]
|
||||
|
||||
|
||||
|
@ -579,9 +579,7 @@ class CableTerminationViewSet(NetBoxModelViewSet):
|
||||
#
|
||||
|
||||
class VirtualChassisViewSet(NetBoxModelViewSet):
|
||||
queryset = VirtualChassis.objects.prefetch_related('tags').annotate(
|
||||
member_count=count_related(Device, 'virtual_chassis')
|
||||
)
|
||||
queryset = VirtualChassis.objects.prefetch_related('tags')
|
||||
serializer_class = serializers.VirtualChassisSerializer
|
||||
filterset_class = filtersets.VirtualChassisFilterSet
|
||||
brief_prefetch_fields = ['master']
|
||||
|
@ -9,7 +9,7 @@ class DCIMConfig(AppConfig):
|
||||
|
||||
def ready(self):
|
||||
from . import signals, search
|
||||
from .models import CableTermination, Device
|
||||
from .models import CableTermination, Device, VirtualChassis
|
||||
from utilities.counters import connect_counters
|
||||
|
||||
# Register denormalized fields
|
||||
@ -27,4 +27,4 @@ class DCIMConfig(AppConfig):
|
||||
})
|
||||
|
||||
# Register counters
|
||||
connect_counters(Device)
|
||||
connect_counters(Device, VirtualChassis)
|
||||
|
@ -0,0 +1,35 @@
|
||||
from django.db import migrations
|
||||
from django.db.models import Count
|
||||
|
||||
import utilities.fields
|
||||
|
||||
|
||||
def populate_virtualchassis_members(apps, schema_editor):
|
||||
VirtualChassis = apps.get_model('dcim', 'VirtualChassis')
|
||||
|
||||
vcs = list(VirtualChassis.objects.annotate(_member_count=Count('members', distinct=True)))
|
||||
|
||||
for vc in vcs:
|
||||
vc.member_count = vc._member_count
|
||||
|
||||
VirtualChassis.objects.bulk_update(vcs, ['member_count'])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('dcim', '0176_device_component_counters'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='virtualchassis',
|
||||
name='member_count',
|
||||
field=utilities.fields.CounterCacheField(
|
||||
default=0, to_field='virtual_chassis', to_model='dcim.Device'
|
||||
),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=populate_virtualchassis_members,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
@ -22,6 +22,7 @@ from netbox.config import ConfigItem
|
||||
from netbox.models import OrganizationalModel, PrimaryModel
|
||||
from utilities.choices import ColorChoices
|
||||
from utilities.fields import ColorField, CounterCacheField, NaturalOrderingField
|
||||
from utilities.tracking import TrackingModelMixin
|
||||
from .device_components import *
|
||||
from .mixins import WeightMixin
|
||||
|
||||
@ -469,7 +470,7 @@ def update_interface_bridges(device, interface_templates, module=None):
|
||||
interface.save()
|
||||
|
||||
|
||||
class Device(PrimaryModel, ConfigContextModel):
|
||||
class Device(PrimaryModel, ConfigContextModel, TrackingModelMixin):
|
||||
"""
|
||||
A Device represents a piece of physical hardware mounted within a Rack. Each Device is assigned a DeviceType,
|
||||
DeviceRole, and (optionally) a Platform. Device names are not required, however if one is set it must be unique.
|
||||
@ -1206,6 +1207,12 @@ class VirtualChassis(PrimaryModel):
|
||||
blank=True
|
||||
)
|
||||
|
||||
# Counter fields
|
||||
member_count = CounterCacheField(
|
||||
to_model='dcim.Device',
|
||||
to_field='virtual_chassis'
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
verbose_name_plural = 'virtual chassis'
|
||||
|
@ -3227,9 +3227,7 @@ class InterfaceConnectionsListView(generic.ObjectListView):
|
||||
#
|
||||
|
||||
class VirtualChassisListView(generic.ObjectListView):
|
||||
queryset = VirtualChassis.objects.annotate(
|
||||
member_count=count_related(Device, 'virtual_chassis')
|
||||
)
|
||||
queryset = VirtualChassis.objects.all()
|
||||
table = tables.VirtualChassisTable
|
||||
filterset = filtersets.VirtualChassisFilterSet
|
||||
filterset_form = forms.VirtualChassisFilterForm
|
||||
|
@ -31,6 +31,16 @@
|
||||
<th scope="row">Description</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Members</th>
|
||||
<td>
|
||||
{% if object.member_count %}
|
||||
<a href="{% url 'dcim:device_list' %}?virtual_chassis_id={{ object.pk }}">{{ object.member_count }}</a>
|
||||
{% else %}
|
||||
{{ object.member_count }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user