Closes #5892: Introduce SiteGroup model (#5937)

* Initial work on #5892

* Add site group selection to object edit forms

* Add documentation for site groups

* Changelog for #5892

* Finish application of site groups to config context
This commit is contained in:
Jeremy Stretch
2021-03-08 13:28:53 -05:00
committed by GitHub
parent 9b5842cff8
commit a4944f2b97
44 changed files with 1388 additions and 232 deletions

View File

@@ -5,9 +5,9 @@ from rest_framework import serializers
from dcim.api.nested_serializers import (
NestedDeviceSerializer, NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedRackSerializer,
NestedRegionSerializer, NestedSiteSerializer,
NestedRegionSerializer, NestedSiteSerializer, NestedSiteGroupSerializer,
)
from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site
from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site, SiteGroup
from extras.choices import *
from extras.models import (
ConfigContext, CustomField, ExportTemplate, ImageAttachment, ObjectChange, JobResult, Tag,
@@ -166,6 +166,12 @@ class ConfigContextSerializer(ValidatedModelSerializer):
required=False,
many=True
)
site_groups = SerializedPKRelatedField(
queryset=SiteGroup.objects.all(),
serializer=NestedSiteGroupSerializer,
required=False,
many=True
)
sites = SerializedPKRelatedField(
queryset=Site.objects.all(),
serializer=NestedSiteSerializer,
@@ -218,8 +224,9 @@ class ConfigContextSerializer(ValidatedModelSerializer):
class Meta:
model = ConfigContext
fields = [
'id', 'url', 'name', 'weight', 'description', 'is_active', 'regions', 'sites', 'roles', 'platforms',
'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'tags', 'data', 'created', 'last_updated',
'id', 'url', 'name', 'weight', 'description', 'is_active', 'regions', 'site_groups', 'sites', 'roles',
'platforms', 'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'tags', 'data', 'created',
'last_updated',
]

View File

@@ -124,7 +124,7 @@ class ImageAttachmentViewSet(ModelViewSet):
class ConfigContextViewSet(ModelViewSet):
queryset = ConfigContext.objects.prefetch_related(
'regions', 'sites', 'roles', 'platforms', 'tenant_groups', 'tenants',
'regions', 'site_groups', 'sites', 'roles', 'platforms', 'tenant_groups', 'tenants',
)
serializer_class = serializers.ConfigContextSerializer
filterset_class = filters.ConfigContextFilterSet

View File

@@ -4,7 +4,7 @@ from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from django.forms import DateField, IntegerField, NullBooleanField
from dcim.models import DeviceRole, Platform, Region, Site
from dcim.models import DeviceRole, Platform, Region, Site, SiteGroup
from tenancy.models import Tenant, TenantGroup
from utilities.filters import BaseFilterSet, ContentTypeFilter
from virtualization.models import Cluster, ClusterGroup
@@ -129,6 +129,17 @@ class ConfigContextFilterSet(BaseFilterSet):
to_field_name='slug',
label='Region (slug)',
)
site_group = django_filters.ModelMultipleChoiceFilter(
field_name='site_groups__slug',
queryset=SiteGroup.objects.all(),
to_field_name='slug',
label='Site group (slug)',
)
site_group_id = django_filters.ModelMultipleChoiceFilter(
field_name='site_groups',
queryset=SiteGroup.objects.all(),
label='Site group',
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='sites',
queryset=Site.objects.all(),

View File

@@ -4,7 +4,7 @@ from django.contrib.contenttypes.models import ContentType
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
from dcim.models import DeviceRole, Platform, Region, Site
from dcim.models import DeviceRole, Platform, Region, Site, SiteGroup
from tenancy.models import Tenant, TenantGroup
from utilities.forms import (
add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect,
@@ -210,6 +210,10 @@ class ConfigContextForm(BootstrapMixin, forms.ModelForm):
queryset=Region.objects.all(),
required=False
)
site_groups = DynamicModelMultipleChoiceField(
queryset=SiteGroup.objects.all(),
required=False
)
sites = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(),
required=False
@@ -249,8 +253,8 @@ class ConfigContextForm(BootstrapMixin, forms.ModelForm):
class Meta:
model = ConfigContext
fields = (
'name', 'weight', 'description', 'is_active', 'regions', 'sites', 'roles', 'platforms', 'cluster_groups',
'clusters', 'tenant_groups', 'tenants', 'tags', 'data',
'name', 'weight', 'description', 'is_active', 'regions', 'site_groups', 'sites', 'roles', 'platforms',
'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'tags', 'data',
)
@@ -280,8 +284,8 @@ class ConfigContextBulkEditForm(BootstrapMixin, BulkEditForm):
class ConfigContextFilterForm(BootstrapMixin, forms.Form):
field_order = [
'q', 'region_id', 'site_id', 'role_id', 'platform_id', 'cluster_group_id', 'cluster_id', 'tenant_group_id',
'tenant_id',
'q', 'region_id', 'site_group_id', 'site_id', 'role_id', 'platform_id', 'cluster_group_id', 'cluster_id',
'tenant_group_id', 'tenant_id',
]
q = forms.CharField(
required=False,
@@ -292,6 +296,11 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
required=False,
label=_('Regions')
)
site_group_id = DynamicModelMultipleChoiceField(
queryset=SiteGroup.objects.all(),
required=False,
label=_('Site groups')
)
site_id = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(),
required=False,

View File

@@ -0,0 +1,17 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dcim', '0130_sitegroup'),
('extras', '0055_objectchange_data'),
]
operations = [
migrations.AddField(
model_name='configcontext',
name='site_groups',
field=models.ManyToManyField(blank=True, related_name='_extras_configcontext_site_groups_+', to='dcim.SiteGroup'),
),
]

View File

@@ -386,6 +386,11 @@ class ConfigContext(ChangeLoggingMixin, BigIDModel):
related_name='+',
blank=True
)
site_groups = models.ManyToManyField(
to='dcim.SiteGroup',
related_name='+',
blank=True
)
sites = models.ManyToManyField(
to='dcim.Site',
related_name='+',

View File

@@ -4,7 +4,7 @@ from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from dcim.models import DeviceRole, Platform, Rack, Region, Site
from dcim.models import DeviceRole, Platform, Rack, Region, Site, SiteGroup
from extras.choices import ObjectChangeActionChoices
from extras.filters import *
from extras.models import ConfigContext, ExportTemplate, ImageAttachment, ObjectChange, Tag
@@ -132,10 +132,17 @@ class ConfigContextTestCase(TestCase):
Region(name='Test Region 2', slug='test-region-2'),
Region(name='Test Region 3', slug='test-region-3'),
)
# Can't use bulk_create for models with MPTT fields
for r in regions:
r.save()
site_groups = (
SiteGroup(name='Site Group 1', slug='site-group-1'),
SiteGroup(name='Site Group 2', slug='site-group-2'),
SiteGroup(name='Site Group 3', slug='site-group-3'),
)
for site_group in site_groups:
site_group.save()
sites = (
Site(name='Test Site 1', slug='test-site-1'),
Site(name='Test Site 2', slug='test-site-2'),
@@ -195,6 +202,7 @@ class ConfigContextTestCase(TestCase):
data='{"foo": 123}'
)
c.regions.set([regions[i]])
c.site_groups.set([site_groups[i]])
c.sites.set([sites[i]])
c.roles.set([device_roles[i]])
c.platforms.set([platforms[i]])
@@ -224,6 +232,13 @@ class ConfigContextTestCase(TestCase):
params = {'region': [regions[0].slug, regions[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_site_group(self):
site_groups = SiteGroup.objects.all()[:2]
params = {'site_group_id': [site_groups[0].pk, site_groups[1].pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
params = {'site_group': [site_groups[0].slug, site_groups[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_site(self):
sites = Site.objects.all()[:2]
params = {'site_id': [sites[0].pk, sites[1].pk]}