mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Merge pull request #4370 from netbox-community/4078-standardize-fields
Closes #4078: Standardize description fields
This commit is contained in:
commit
36130965f2
@ -20,13 +20,24 @@ If further customization of remote authentication is desired (for instance, if y
|
||||
|
||||
* [#1754](https://github.com/netbox-community/netbox/issues/1754) - Added support for nested rack groups
|
||||
* [#3939](https://github.com/netbox-community/netbox/issues/3939) - Added support for nested tenant groups
|
||||
* [#4078](https://github.com/netbox-community/netbox/issues/4078) - Standardized description fields across all models
|
||||
* [#4195](https://github.com/netbox-community/netbox/issues/4195) - Enabled application logging (see [logging configuration](../configuration/optional-settings.md#logging))
|
||||
|
||||
### API Changes
|
||||
|
||||
* The `_choices` API endpoints have been removed. Instead, use an `OPTIONS` request to a model's endpoint to view the available values for all fields. ([#3416](https://github.com/netbox-community/netbox/issues/3416))
|
||||
* The `id__in` filter has been removed. Use the format `?id=1&id=2` instead. ([#4313](https://github.com/netbox-community/netbox/issues/4313))
|
||||
* dcim.Manufacturer: Added a `description` field
|
||||
* dcim.Platform: Added a `description` field
|
||||
* dcim.Rack: The `/api/dcim/racks/<pk>/units/` endpoint has been replaced with `/api/dcim/racks/<pk>/elevation/`.
|
||||
* dcim.RackGroup: Added a `description` field
|
||||
* dcim.Region: Added a `description` field
|
||||
* extras.Tag: Renamed `comments` to `description`; truncated length to 200 characters; removed Markdown rendering
|
||||
* ipam.RIR: Added a `description` field
|
||||
* ipam.VLANGroup: Added a `description` field
|
||||
* tenancy.TenantGroup: Added a `description` field
|
||||
* virtualization.ClusterGroup: Added a `description` field
|
||||
* virtualization.ClusterType: Added a `description` field
|
||||
|
||||
### Other Changes
|
||||
|
||||
|
28
netbox/circuits/migrations/0008_standardize_description.py
Normal file
28
netbox/circuits/migrations/0008_standardize_description.py
Normal file
@ -0,0 +1,28 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-13 20:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('circuits', '0007_circuit_add_description_squashed_0017_circuittype_description'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='circuit',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='circuittermination',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='circuittype',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
]
|
@ -108,7 +108,7 @@ class CircuitType(ChangeLoggedModel):
|
||||
unique=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
@ -173,7 +173,7 @@ class Circuit(ChangeLoggedModel, CustomFieldModel):
|
||||
null=True,
|
||||
verbose_name='Commit rate (Kbps)')
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
comments = models.TextField(
|
||||
@ -292,7 +292,7 @@ class CircuitTermination(CableTermination):
|
||||
verbose_name='Patch panel/port(s)'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
|
@ -64,7 +64,7 @@ class RegionSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Region
|
||||
fields = ['id', 'name', 'slug', 'parent', 'site_count']
|
||||
fields = ['id', 'name', 'slug', 'parent', 'description', 'site_count']
|
||||
|
||||
|
||||
class SiteSerializer(TaggitSerializer, CustomFieldModelSerializer):
|
||||
@ -101,7 +101,7 @@ class RackGroupSerializer(ValidatedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = RackGroup
|
||||
fields = ['id', 'name', 'slug', 'site', 'parent', 'rack_count']
|
||||
fields = ['id', 'name', 'slug', 'site', 'parent', 'description', 'rack_count']
|
||||
|
||||
|
||||
class RackRoleSerializer(ValidatedModelSerializer):
|
||||
@ -219,7 +219,9 @@ class ManufacturerSerializer(ValidatedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Manufacturer
|
||||
fields = ['id', 'name', 'slug', 'devicetype_count', 'inventoryitem_count', 'platform_count']
|
||||
fields = [
|
||||
'id', 'name', 'slug', 'description', 'devicetype_count', 'inventoryitem_count', 'platform_count',
|
||||
]
|
||||
|
||||
|
||||
class DeviceTypeSerializer(TaggitSerializer, CustomFieldModelSerializer):
|
||||
@ -356,7 +358,7 @@ class PlatformSerializer(ValidatedModelSerializer):
|
||||
class Meta:
|
||||
model = Platform
|
||||
fields = [
|
||||
'id', 'name', 'slug', 'manufacturer', 'napalm_driver', 'napalm_args', 'device_count',
|
||||
'id', 'name', 'slug', 'manufacturer', 'napalm_driver', 'napalm_args', 'description', 'device_count',
|
||||
'virtualmachine_count',
|
||||
]
|
||||
|
||||
|
@ -74,7 +74,7 @@ class RegionFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = Region
|
||||
fields = ['id', 'name', 'slug']
|
||||
fields = ['id', 'name', 'slug', 'description']
|
||||
|
||||
|
||||
class SiteFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
||||
@ -166,7 +166,7 @@ class RackGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = RackGroup
|
||||
fields = ['id', 'name', 'slug']
|
||||
fields = ['id', 'name', 'slug', 'description']
|
||||
|
||||
|
||||
class RackRoleFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
@ -318,7 +318,7 @@ class ManufacturerFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = Manufacturer
|
||||
fields = ['id', 'name', 'slug']
|
||||
fields = ['id', 'name', 'slug', 'description']
|
||||
|
||||
|
||||
class DeviceTypeFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
||||
@ -493,7 +493,7 @@ class PlatformFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = Platform
|
||||
fields = ['id', 'name', 'slug', 'napalm_driver']
|
||||
fields = ['id', 'name', 'slug', 'napalm_driver', 'description']
|
||||
|
||||
|
||||
class DeviceFilterSet(
|
||||
|
@ -192,7 +192,7 @@ class RegionForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = Region
|
||||
fields = (
|
||||
'parent', 'name', 'slug',
|
||||
'parent', 'name', 'slug', 'description',
|
||||
)
|
||||
|
||||
|
||||
@ -404,7 +404,7 @@ class RackGroupForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = RackGroup
|
||||
fields = (
|
||||
'site', 'parent', 'name', 'slug',
|
||||
'site', 'parent', 'name', 'slug', 'description',
|
||||
)
|
||||
|
||||
|
||||
@ -983,7 +983,7 @@ class ManufacturerForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = Manufacturer
|
||||
fields = [
|
||||
'name', 'slug',
|
||||
'name', 'slug', 'description',
|
||||
]
|
||||
|
||||
|
||||
@ -1768,7 +1768,7 @@ class PlatformForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = Platform
|
||||
fields = [
|
||||
'name', 'slug', 'manufacturer', 'napalm_driver', 'napalm_args',
|
||||
'name', 'slug', 'manufacturer', 'napalm_driver', 'napalm_args', 'description',
|
||||
]
|
||||
widgets = {
|
||||
'napalm_args': SmallTextarea(),
|
||||
|
98
netbox/dcim/migrations/0103_standardize_description.py
Normal file
98
netbox/dcim/migrations/0103_standardize_description.py
Normal file
@ -0,0 +1,98 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-13 20:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dcim', '0102_nested_rackgroups_rebuild'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='manufacturer',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platform',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='rackgroup',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='region',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='consoleport',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='consoleserverport',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicebay',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicerole',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='frontport',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='interface',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='inventoryitem',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='poweroutlet',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='powerport',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rackreservation',
|
||||
name='description',
|
||||
field=models.CharField(max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rackrole',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='rearport',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='site',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
]
|
@ -94,8 +94,12 @@ class Region(MPTTModel, ChangeLoggedModel):
|
||||
slug = models.SlugField(
|
||||
unique=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
csv_headers = ['name', 'slug', 'parent']
|
||||
csv_headers = ['name', 'slug', 'parent', 'description']
|
||||
|
||||
class MPTTMeta:
|
||||
order_insertion_by = ['name']
|
||||
@ -111,6 +115,7 @@ class Region(MPTTModel, ChangeLoggedModel):
|
||||
self.name,
|
||||
self.slug,
|
||||
self.parent.name if self.parent else None,
|
||||
self.description,
|
||||
)
|
||||
|
||||
def get_site_count(self):
|
||||
@ -182,7 +187,7 @@ class Site(ChangeLoggedModel, CustomFieldModel):
|
||||
blank=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
physical_address = models.CharField(
|
||||
@ -306,8 +311,12 @@ class RackGroup(MPTTModel, ChangeLoggedModel):
|
||||
null=True,
|
||||
db_index=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
csv_headers = ['site', 'parent', 'name', 'slug']
|
||||
csv_headers = ['site', 'parent', 'name', 'slug', 'description']
|
||||
|
||||
class Meta:
|
||||
ordering = ['site', 'name']
|
||||
@ -331,6 +340,7 @@ class RackGroup(MPTTModel, ChangeLoggedModel):
|
||||
self.parent.name if self.parent else '',
|
||||
self.name,
|
||||
self.slug,
|
||||
self.description,
|
||||
)
|
||||
|
||||
def to_objectchange(self, action):
|
||||
@ -362,7 +372,7 @@ class RackRole(ChangeLoggedModel):
|
||||
)
|
||||
color = ColorField()
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
@ -785,7 +795,7 @@ class RackReservation(ChangeLoggedModel):
|
||||
on_delete=models.PROTECT
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100
|
||||
max_length=200
|
||||
)
|
||||
|
||||
csv_headers = ['site', 'rack_group', 'rack', 'units', 'tenant', 'user', 'description']
|
||||
@ -858,8 +868,12 @@ class Manufacturer(ChangeLoggedModel):
|
||||
slug = models.SlugField(
|
||||
unique=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
csv_headers = ['name', 'slug']
|
||||
csv_headers = ['name', 'slug', 'description']
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
@ -874,6 +888,7 @@ class Manufacturer(ChangeLoggedModel):
|
||||
return (
|
||||
self.name,
|
||||
self.slug,
|
||||
self.description
|
||||
)
|
||||
|
||||
|
||||
@ -1142,7 +1157,7 @@ class DeviceRole(ChangeLoggedModel):
|
||||
help_text='Virtual machines may be assigned to this role'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
@ -1198,8 +1213,12 @@ class Platform(ChangeLoggedModel):
|
||||
verbose_name='NAPALM arguments',
|
||||
help_text='Additional arguments to pass when initiating the NAPALM driver (JSON format)'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
csv_headers = ['name', 'slug', 'manufacturer', 'napalm_driver', 'napalm_args']
|
||||
csv_headers = ['name', 'slug', 'manufacturer', 'napalm_driver', 'napalm_args', 'description']
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
@ -1217,6 +1236,7 @@ class Platform(ChangeLoggedModel):
|
||||
self.manufacturer.name if self.manufacturer else None,
|
||||
self.napalm_driver,
|
||||
self.napalm_args,
|
||||
self.description,
|
||||
)
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ __all__ = (
|
||||
|
||||
class ComponentModel(models.Model):
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
|
@ -225,7 +225,7 @@ class RegionTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = Region
|
||||
fields = ('pk', 'name', 'site_count', 'slug', 'actions')
|
||||
fields = ('pk', 'name', 'site_count', 'description', 'slug', 'actions')
|
||||
|
||||
|
||||
#
|
||||
@ -271,7 +271,7 @@ class RackGroupTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = RackGroup
|
||||
fields = ('pk', 'name', 'site', 'rack_count', 'slug', 'actions')
|
||||
fields = ('pk', 'name', 'site', 'rack_count', 'description', 'slug', 'actions')
|
||||
|
||||
|
||||
#
|
||||
@ -383,7 +383,9 @@ class ManufacturerTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = Manufacturer
|
||||
fields = ('pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'slug', 'actions')
|
||||
fields = (
|
||||
'pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug', 'actions',
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
@ -659,7 +661,9 @@ class PlatformTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = Platform
|
||||
fields = ('pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'actions')
|
||||
fields = (
|
||||
'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'description', 'actions',
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
|
@ -17,14 +17,15 @@ from virtualization.models import Cluster, ClusterType
|
||||
|
||||
class RegionTestCase(TestCase):
|
||||
queryset = Region.objects.all()
|
||||
filterset = RegionFilterSet
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
|
||||
regions = (
|
||||
Region(name='Region 1', slug='region-1'),
|
||||
Region(name='Region 2', slug='region-2'),
|
||||
Region(name='Region 3', slug='region-3'),
|
||||
Region(name='Region 1', slug='region-1', description='A'),
|
||||
Region(name='Region 2', slug='region-2', description='B'),
|
||||
Region(name='Region 3', slug='region-3', description='C'),
|
||||
)
|
||||
for region in regions:
|
||||
region.save()
|
||||
@ -43,22 +44,26 @@ class RegionTestCase(TestCase):
|
||||
def test_id(self):
|
||||
id_list = self.queryset.values_list('id', flat=True)[:2]
|
||||
params = {'id': [str(id) for id in id_list]}
|
||||
self.assertEqual(RegionFilterSet(params, self.queryset).qs.count(), 2)
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_name(self):
|
||||
params = {'name': ['Region 1', 'Region 2']}
|
||||
self.assertEqual(RegionFilterSet(params, self.queryset).qs.count(), 2)
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_slug(self):
|
||||
params = {'slug': ['region-1', 'region-2']}
|
||||
self.assertEqual(RegionFilterSet(params, self.queryset).qs.count(), 2)
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_parent(self):
|
||||
parent_regions = Region.objects.filter(parent__isnull=True)[:2]
|
||||
params = {'parent_id': [parent_regions[0].pk, parent_regions[1].pk]}
|
||||
self.assertEqual(RegionFilterSet(params, self.queryset).qs.count(), 4)
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
|
||||
params = {'parent': [parent_regions[0].slug, parent_regions[1].slug]}
|
||||
self.assertEqual(RegionFilterSet(params, self.queryset).qs.count(), 4)
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
|
||||
|
||||
|
||||
class SiteTestCase(TestCase):
|
||||
@ -196,9 +201,9 @@ class RackGroupTestCase(TestCase):
|
||||
rackgroup.save()
|
||||
|
||||
rack_groups = (
|
||||
RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0], parent=parent_rack_groups[0]),
|
||||
RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1], parent=parent_rack_groups[1]),
|
||||
RackGroup(name='Rack Group 3', slug='rack-group-3', site=sites[2], parent=parent_rack_groups[2]),
|
||||
RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0], parent=parent_rack_groups[0], description='A'),
|
||||
RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1], parent=parent_rack_groups[1], description='B'),
|
||||
RackGroup(name='Rack Group 3', slug='rack-group-3', site=sites[2], parent=parent_rack_groups[2], description='C'),
|
||||
)
|
||||
for rackgroup in rack_groups:
|
||||
rackgroup.save()
|
||||
@ -216,6 +221,10 @@ class RackGroupTestCase(TestCase):
|
||||
params = {'slug': ['rack-group-1', 'rack-group-2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_region(self):
|
||||
regions = Region.objects.all()[:2]
|
||||
params = {'region_id': [regions[0].pk, regions[1].pk]}
|
||||
@ -535,9 +544,9 @@ class ManufacturerTestCase(TestCase):
|
||||
def setUpTestData(cls):
|
||||
|
||||
manufacturers = (
|
||||
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
|
||||
Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
|
||||
Manufacturer(name='Manufacturer 3', slug='manufacturer-3'),
|
||||
Manufacturer(name='Manufacturer 1', slug='manufacturer-1', description='A'),
|
||||
Manufacturer(name='Manufacturer 2', slug='manufacturer-2', description='B'),
|
||||
Manufacturer(name='Manufacturer 3', slug='manufacturer-3', description='C'),
|
||||
)
|
||||
Manufacturer.objects.bulk_create(manufacturers)
|
||||
|
||||
@ -554,6 +563,10 @@ class ManufacturerTestCase(TestCase):
|
||||
params = {'slug': ['manufacturer-1', 'manufacturer-2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
|
||||
class DeviceTypeTestCase(TestCase):
|
||||
queryset = DeviceType.objects.all()
|
||||
@ -1081,9 +1094,9 @@ class PlatformTestCase(TestCase):
|
||||
Manufacturer.objects.bulk_create(manufacturers)
|
||||
|
||||
platforms = (
|
||||
Platform(name='Platform 1', slug='platform-1', manufacturer=manufacturers[0], napalm_driver='driver-1'),
|
||||
Platform(name='Platform 2', slug='platform-2', manufacturer=manufacturers[1], napalm_driver='driver-2'),
|
||||
Platform(name='Platform 3', slug='platform-3', manufacturer=manufacturers[2], napalm_driver='driver-3'),
|
||||
Platform(name='Platform 1', slug='platform-1', manufacturer=manufacturers[0], napalm_driver='driver-1', description='A'),
|
||||
Platform(name='Platform 2', slug='platform-2', manufacturer=manufacturers[1], napalm_driver='driver-2', description='B'),
|
||||
Platform(name='Platform 3', slug='platform-3', manufacturer=manufacturers[2], napalm_driver='driver-3', description='C'),
|
||||
)
|
||||
Platform.objects.bulk_create(platforms)
|
||||
|
||||
@ -1100,6 +1113,10 @@ class PlatformTestCase(TestCase):
|
||||
params = {'slug': ['platform-1', 'platform-2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_napalm_driver(self):
|
||||
params = {'napalm_driver': ['driver-1', 'driver-2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
@ -46,13 +46,14 @@ class RegionTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
'name': 'Region X',
|
||||
'slug': 'region-x',
|
||||
'parent': regions[2].pk,
|
||||
'description': 'A new region',
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"name,slug",
|
||||
"Region 4,region-4",
|
||||
"Region 5,region-5",
|
||||
"Region 6,region-6",
|
||||
"name,slug,description",
|
||||
"Region 4,region-4,Fourth region",
|
||||
"Region 5,region-5,Fifth region",
|
||||
"Region 6,region-6,Sixth region",
|
||||
)
|
||||
|
||||
|
||||
@ -134,13 +135,14 @@ class RackGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
'name': 'Rack Group X',
|
||||
'slug': 'rack-group-x',
|
||||
'site': site.pk,
|
||||
'description': 'A new rack group',
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"site,name,slug",
|
||||
"Site 1,Rack Group 4,rack-group-4",
|
||||
"Site 1,Rack Group 5,rack-group-5",
|
||||
"Site 1,Rack Group 6,rack-group-6",
|
||||
"site,name,slug,description",
|
||||
"Site 1,Rack Group 4,rack-group-4,Fourth rack group",
|
||||
"Site 1,Rack Group 5,rack-group-5,Fifth rack group",
|
||||
"Site 1,Rack Group 6,rack-group-6,Sixth rack group",
|
||||
)
|
||||
|
||||
|
||||
@ -309,13 +311,14 @@ class ManufacturerTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
cls.form_data = {
|
||||
'name': 'Manufacturer X',
|
||||
'slug': 'manufacturer-x',
|
||||
'description': 'A new manufacturer',
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"name,slug",
|
||||
"Manufacturer 4,manufacturer-4",
|
||||
"Manufacturer 5,manufacturer-5",
|
||||
"Manufacturer 6,manufacturer-6",
|
||||
"name,slug,description",
|
||||
"Manufacturer 4,manufacturer-4,Fourth manufacturer",
|
||||
"Manufacturer 5,manufacturer-5,Fifth manufacturer",
|
||||
"Manufacturer 6,manufacturer-6,Sixth manufacturer",
|
||||
)
|
||||
|
||||
|
||||
@ -868,13 +871,14 @@ class PlatformTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
'manufacturer': manufacturer.pk,
|
||||
'napalm_driver': 'junos',
|
||||
'napalm_args': None,
|
||||
'description': 'A new platform',
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"name,slug",
|
||||
"Platform 4,platform-4",
|
||||
"Platform 5,platform-5",
|
||||
"Platform 6,platform-6",
|
||||
"name,slug,description",
|
||||
"Platform 4,platform-4,Fourth platform",
|
||||
"Platform 5,platform-5,Fifth platform",
|
||||
"Platform 6,platform-6,Sixth platform",
|
||||
)
|
||||
|
||||
|
||||
|
@ -91,7 +91,7 @@ class TagSerializer(ValidatedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Tag
|
||||
fields = ['id', 'name', 'slug', 'color', 'comments', 'tagged_items']
|
||||
fields = ['id', 'name', 'slug', 'color', 'description', 'tagged_items']
|
||||
|
||||
|
||||
#
|
||||
|
@ -144,12 +144,11 @@ class CustomFieldFilterForm(forms.Form):
|
||||
|
||||
class TagForm(BootstrapMixin, forms.ModelForm):
|
||||
slug = SlugField()
|
||||
comments = CommentField()
|
||||
|
||||
class Meta:
|
||||
model = Tag
|
||||
fields = [
|
||||
'name', 'slug', 'color', 'comments'
|
||||
'name', 'slug', 'color', 'description'
|
||||
]
|
||||
|
||||
|
||||
@ -181,9 +180,13 @@ class TagBulkEditForm(BootstrapMixin, BulkEditForm):
|
||||
required=False,
|
||||
widget=ColorSelect()
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
nullable_fields = []
|
||||
nullable_fields = ['description']
|
||||
|
||||
|
||||
#
|
||||
|
23
netbox/extras/migrations/0039_standardize_description.py
Normal file
23
netbox/extras/migrations/0039_standardize_description.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-13 20:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('extras', '0038_webhook_template_support'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='configcontext',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='customfield',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
]
|
23
netbox/extras/migrations/0040_tag_description.py
Normal file
23
netbox/extras/migrations/0040_tag_description.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-13 20:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('extras', '0039_standardize_description'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='tag',
|
||||
name='comments',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='tag',
|
||||
old_name='comments',
|
||||
new_name='description',
|
||||
),
|
||||
]
|
@ -242,7 +242,7 @@ class CustomField(models.Model):
|
||||
'the field\'s name will be used)'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
required = models.BooleanField(
|
||||
@ -764,7 +764,7 @@ class ConfigContext(models.Model):
|
||||
default=1000
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
is_active = models.BooleanField(
|
||||
@ -1051,9 +1051,9 @@ class Tag(TagBase, ChangeLoggedModel):
|
||||
color = ColorField(
|
||||
default='9e9e9e'
|
||||
)
|
||||
comments = models.TextField(
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True,
|
||||
default=''
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
|
@ -77,7 +77,7 @@ class TagTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = Tag
|
||||
fields = ('pk', 'name', 'items', 'slug', 'color', 'actions')
|
||||
fields = ('pk', 'name', 'items', 'slug', 'color', 'description', 'actions')
|
||||
|
||||
|
||||
class TaggedItemTable(BaseTable):
|
||||
|
@ -45,7 +45,7 @@ class RIRSerializer(ValidatedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = RIR
|
||||
fields = ['id', 'name', 'slug', 'is_private', 'aggregate_count']
|
||||
fields = ['id', 'name', 'slug', 'is_private', 'description', 'aggregate_count']
|
||||
|
||||
|
||||
class AggregateSerializer(TaggitSerializer, CustomFieldModelSerializer):
|
||||
@ -81,7 +81,7 @@ class VLANGroupSerializer(ValidatedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = VLANGroup
|
||||
fields = ['id', 'name', 'slug', 'site', 'vlan_count']
|
||||
fields = ['id', 'name', 'slug', 'site', 'description', 'vlan_count']
|
||||
validators = []
|
||||
|
||||
def validate(self, data):
|
||||
|
@ -54,7 +54,7 @@ class RIRFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = RIR
|
||||
fields = ['name', 'slug', 'is_private']
|
||||
fields = ['name', 'slug', 'is_private', 'description']
|
||||
|
||||
|
||||
class AggregateFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
||||
@ -419,7 +419,7 @@ class VLANGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = VLANGroup
|
||||
fields = ['id', 'name', 'slug']
|
||||
fields = ['id', 'name', 'slug', 'description']
|
||||
|
||||
|
||||
class VLANFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
||||
|
@ -119,7 +119,7 @@ class RIRForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = RIR
|
||||
fields = [
|
||||
'name', 'slug', 'is_private',
|
||||
'name', 'slug', 'is_private', 'description',
|
||||
]
|
||||
|
||||
|
||||
@ -1048,7 +1048,7 @@ class VLANGroupForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = VLANGroup
|
||||
fields = [
|
||||
'site', 'name', 'slug',
|
||||
'site', 'name', 'slug', 'description',
|
||||
]
|
||||
|
||||
|
||||
|
58
netbox/ipam/migrations/0036_standardize_description.py
Normal file
58
netbox/ipam/migrations/0036_standardize_description.py
Normal file
@ -0,0 +1,58 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-13 20:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ipam', '0035_drop_ip_family'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='rir',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='vlangroup',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='aggregate',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ipaddress',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='prefix',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='role',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='service',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='vlan',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='vrf',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
]
|
@ -63,7 +63,7 @@ class VRF(ChangeLoggedModel, CustomFieldModel):
|
||||
help_text='Prevent duplicate prefixes/IP addresses within this VRF'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
custom_field_values = GenericRelation(
|
||||
@ -123,8 +123,12 @@ class RIR(ChangeLoggedModel):
|
||||
verbose_name='Private',
|
||||
help_text='IP space managed by this RIR is considered private'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
csv_headers = ['name', 'slug', 'is_private']
|
||||
csv_headers = ['name', 'slug', 'is_private', 'description']
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
@ -142,6 +146,7 @@ class RIR(ChangeLoggedModel):
|
||||
self.name,
|
||||
self.slug,
|
||||
self.is_private,
|
||||
self.description,
|
||||
)
|
||||
|
||||
|
||||
@ -162,7 +167,7 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel):
|
||||
null=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
custom_field_values = GenericRelation(
|
||||
@ -261,7 +266,7 @@ class Role(ChangeLoggedModel):
|
||||
default=1000
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
@ -342,7 +347,7 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
|
||||
help_text='All IP addresses within this prefix are considered usable'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
custom_field_values = GenericRelation(
|
||||
@ -612,7 +617,7 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel):
|
||||
help_text='Hostname or FQDN (not case-sensitive)'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
custom_field_values = GenericRelation(
|
||||
@ -812,8 +817,12 @@ class VLANGroup(ChangeLoggedModel):
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
csv_headers = ['name', 'slug', 'site']
|
||||
csv_headers = ['name', 'slug', 'site', 'description']
|
||||
|
||||
class Meta:
|
||||
ordering = ('site', 'name', 'pk') # (site, name) may be non-unique
|
||||
@ -835,6 +844,7 @@ class VLANGroup(ChangeLoggedModel):
|
||||
self.name,
|
||||
self.slug,
|
||||
self.site.name if self.site else None,
|
||||
self.description,
|
||||
)
|
||||
|
||||
def get_next_available_vid(self):
|
||||
@ -898,7 +908,7 @@ class VLAN(ChangeLoggedModel, CustomFieldModel):
|
||||
null=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
custom_field_values = GenericRelation(
|
||||
@ -1010,7 +1020,7 @@ class Service(ChangeLoggedModel, CustomFieldModel):
|
||||
verbose_name='IP addresses'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
custom_field_values = GenericRelation(
|
||||
|
@ -211,7 +211,7 @@ class RIRTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = RIR
|
||||
fields = ('pk', 'name', 'is_private', 'aggregate_count', 'actions')
|
||||
fields = ('pk', 'name', 'is_private', 'aggregate_count', 'description', 'actions')
|
||||
|
||||
|
||||
class RIRDetailTable(RIRTable):
|
||||
@ -410,7 +410,7 @@ class VLANGroupTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = VLANGroup
|
||||
fields = ('pk', 'name', 'site', 'vlan_count', 'slug', 'actions')
|
||||
fields = ('pk', 'name', 'site', 'vlan_count', 'slug', 'description', 'actions')
|
||||
|
||||
|
||||
#
|
||||
|
@ -77,12 +77,12 @@ class RIRTestCase(TestCase):
|
||||
def setUpTestData(cls):
|
||||
|
||||
rirs = (
|
||||
RIR(name='RIR 1', slug='rir-1', is_private=False),
|
||||
RIR(name='RIR 2', slug='rir-2', is_private=False),
|
||||
RIR(name='RIR 3', slug='rir-3', is_private=False),
|
||||
RIR(name='RIR 4', slug='rir-4', is_private=True),
|
||||
RIR(name='RIR 5', slug='rir-5', is_private=True),
|
||||
RIR(name='RIR 6', slug='rir-6', is_private=True),
|
||||
RIR(name='RIR 1', slug='rir-1', is_private=False, description='A'),
|
||||
RIR(name='RIR 2', slug='rir-2', is_private=False, description='B'),
|
||||
RIR(name='RIR 3', slug='rir-3', is_private=False, description='C'),
|
||||
RIR(name='RIR 4', slug='rir-4', is_private=True, description='D'),
|
||||
RIR(name='RIR 5', slug='rir-5', is_private=True, description='E'),
|
||||
RIR(name='RIR 6', slug='rir-6', is_private=True, description='F'),
|
||||
)
|
||||
RIR.objects.bulk_create(rirs)
|
||||
|
||||
@ -94,6 +94,10 @@ class RIRTestCase(TestCase):
|
||||
params = {'slug': ['rir-1', 'rir-2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_is_private(self):
|
||||
params = {'is_private': 'true'}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
|
||||
@ -519,9 +523,9 @@ class VLANGroupTestCase(TestCase):
|
||||
Site.objects.bulk_create(sites)
|
||||
|
||||
vlan_groups = (
|
||||
VLANGroup(name='VLAN Group 1', slug='vlan-group-1', site=sites[0]),
|
||||
VLANGroup(name='VLAN Group 2', slug='vlan-group-2', site=sites[1]),
|
||||
VLANGroup(name='VLAN Group 3', slug='vlan-group-3', site=sites[2]),
|
||||
VLANGroup(name='VLAN Group 1', slug='vlan-group-1', site=sites[0], description='A'),
|
||||
VLANGroup(name='VLAN Group 2', slug='vlan-group-2', site=sites[1], description='B'),
|
||||
VLANGroup(name='VLAN Group 3', slug='vlan-group-3', site=sites[2], description='C'),
|
||||
VLANGroup(name='VLAN Group 4', slug='vlan-group-4', site=None),
|
||||
)
|
||||
VLANGroup.objects.bulk_create(vlan_groups)
|
||||
@ -539,6 +543,10 @@ class VLANGroupTestCase(TestCase):
|
||||
params = {'slug': ['vlan-group-1', 'vlan-group-2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_region(self):
|
||||
regions = Region.objects.all()[:2]
|
||||
params = {'region_id': [regions[0].pk, regions[1].pk]}
|
||||
|
@ -59,13 +59,14 @@ class RIRTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
'name': 'RIR X',
|
||||
'slug': 'rir-x',
|
||||
'is_private': True,
|
||||
'description': 'A new RIR',
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"name,slug",
|
||||
"RIR 4,rir-4",
|
||||
"RIR 5,rir-5",
|
||||
"RIR 6,rir-6",
|
||||
"name,slug,description",
|
||||
"RIR 4,rir-4,Fourth RIR",
|
||||
"RIR 5,rir-5,Fifth RIR",
|
||||
"RIR 6,rir-6,Sixth RIR",
|
||||
)
|
||||
|
||||
|
||||
@ -261,13 +262,14 @@ class VLANGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
'name': 'VLAN Group X',
|
||||
'slug': 'vlan-group-x',
|
||||
'site': site.pk,
|
||||
'description': 'A new VLAN group',
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"name,slug",
|
||||
"VLAN Group 4,vlan-group-4",
|
||||
"VLAN Group 5,vlan-group-5",
|
||||
"VLAN Group 6,vlan-group-6",
|
||||
"name,slug,description",
|
||||
"VLAN Group 4,vlan-group-4,Fourth VLAN group",
|
||||
"VLAN Group 5,vlan-group-5,Fifth VLAN group",
|
||||
"VLAN Group 6,vlan-group-6,Sixth VLAN group",
|
||||
)
|
||||
|
||||
|
||||
|
18
netbox/secrets/migrations/0008_standardize_description.py
Normal file
18
netbox/secrets/migrations/0008_standardize_description.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-13 20:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('secrets', '0007_secretrole_description'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='secretrole',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
]
|
@ -254,7 +254,7 @@ class SecretRole(ChangeLoggedModel):
|
||||
unique=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True,
|
||||
)
|
||||
users = models.ManyToManyField(
|
||||
|
@ -82,20 +82,13 @@
|
||||
<span class="label color-block" style="background-color: #{{ tag.color }}"> </span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>
|
||||
{{ tag.description }}
|
||||
</td>
|
||||
</table>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Comments</strong>
|
||||
</div>
|
||||
<div class="panel-body rendered-markdown">
|
||||
{% if tag.comments %}
|
||||
{{ tag.comments|render_markdown }}
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{% include 'panel_table.html' with table=items_table heading='Tagged Objects' %}
|
||||
|
@ -8,12 +8,7 @@
|
||||
{% render_field form.name %}
|
||||
{% render_field form.slug %}
|
||||
{% render_field form.color %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Comments</strong></div>
|
||||
<div class="panel-body">
|
||||
{% render_field form.comments %}
|
||||
{% render_field form.description %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -17,7 +17,7 @@ class TenantGroupSerializer(ValidatedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = TenantGroup
|
||||
fields = ['id', 'name', 'slug', 'parent', 'tenant_count']
|
||||
fields = ['id', 'name', 'slug', 'parent', 'description', 'tenant_count']
|
||||
|
||||
|
||||
class TenantSerializer(TaggitSerializer, CustomFieldModelSerializer):
|
||||
|
@ -27,7 +27,7 @@ class TenantGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = TenantGroup
|
||||
fields = ['id', 'name', 'slug']
|
||||
fields = ['id', 'name', 'slug', 'description']
|
||||
|
||||
|
||||
class TenantFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
||||
|
@ -28,7 +28,7 @@ class TenantGroupForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = TenantGroup
|
||||
fields = [
|
||||
'parent', 'name', 'slug',
|
||||
'parent', 'name', 'slug', 'description',
|
||||
]
|
||||
|
||||
|
||||
|
23
netbox/tenancy/migrations/0009_standardize_description.py
Normal file
23
netbox/tenancy/migrations/0009_standardize_description.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-13 20:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tenancy', '0008_nested_tenantgroups_rebuild'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tenantgroup',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tenant',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
]
|
@ -34,8 +34,12 @@ class TenantGroup(MPTTModel, ChangeLoggedModel):
|
||||
null=True,
|
||||
db_index=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
csv_headers = ['name', 'slug', 'parent']
|
||||
csv_headers = ['name', 'slug', 'parent', 'description']
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
@ -54,6 +58,7 @@ class TenantGroup(MPTTModel, ChangeLoggedModel):
|
||||
self.name,
|
||||
self.slug,
|
||||
self.parent.name if self.parent else '',
|
||||
self.description,
|
||||
)
|
||||
|
||||
def to_objectchange(self, action):
|
||||
@ -86,9 +91,8 @@ class Tenant(ChangeLoggedModel, CustomFieldModel):
|
||||
null=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
blank=True,
|
||||
help_text='Long-form name (optional)'
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
comments = models.TextField(
|
||||
blank=True
|
||||
|
@ -53,7 +53,7 @@ class TenantGroupTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = TenantGroup
|
||||
fields = ('pk', 'name', 'tenant_count', 'slug', 'actions')
|
||||
fields = ('pk', 'name', 'tenant_count', 'description', 'slug', 'actions')
|
||||
|
||||
|
||||
#
|
||||
|
@ -20,9 +20,9 @@ class TenantGroupTestCase(TestCase):
|
||||
tenantgroup.save()
|
||||
|
||||
tenant_groups = (
|
||||
TenantGroup(name='Tenant Group 1', slug='tenant-group-1', parent=parent_tenant_groups[0]),
|
||||
TenantGroup(name='Tenant Group 2', slug='tenant-group-2', parent=parent_tenant_groups[1]),
|
||||
TenantGroup(name='Tenant Group 3', slug='tenant-group-3', parent=parent_tenant_groups[2]),
|
||||
TenantGroup(name='Tenant Group 1', slug='tenant-group-1', parent=parent_tenant_groups[0], description='A'),
|
||||
TenantGroup(name='Tenant Group 2', slug='tenant-group-2', parent=parent_tenant_groups[1], description='B'),
|
||||
TenantGroup(name='Tenant Group 3', slug='tenant-group-3', parent=parent_tenant_groups[2], description='C'),
|
||||
)
|
||||
for tenantgroup in tenant_groups:
|
||||
tenantgroup.save()
|
||||
@ -40,6 +40,10 @@ class TenantGroupTestCase(TestCase):
|
||||
params = {'slug': ['tenant-group-1', 'tenant-group-2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_parent(self):
|
||||
parent_groups = TenantGroup.objects.filter(name__startswith='Parent')[:2]
|
||||
params = {'parent_id': [parent_groups[0].pk, parent_groups[1].pk]}
|
||||
|
@ -19,13 +19,14 @@ class TenantGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
cls.form_data = {
|
||||
'name': 'Tenant Group X',
|
||||
'slug': 'tenant-group-x',
|
||||
'description': 'A new tenant group',
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"name,slug",
|
||||
"Tenant Group 4,tenant-group-4",
|
||||
"Tenant Group 5,tenant-group-5",
|
||||
"Tenant Group 6,tenant-group-6",
|
||||
"name,slug,description",
|
||||
"Tenant Group 4,tenant-group-4,Fourth tenant group",
|
||||
"Tenant Group 5,tenant-group-5,Fifth tenant group",
|
||||
"Tenant Group 6,tenant-group-6,Sixth tenant group",
|
||||
)
|
||||
|
||||
|
||||
|
18
netbox/users/migrations/0002_standardize_description.py
Normal file
18
netbox/users/migrations/0002_standardize_description.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-13 20:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0001_api_tokens_squashed_0003_token_permissions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='token',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
]
|
@ -39,7 +39,7 @@ class Token(models.Model):
|
||||
help_text='Permit create/update/delete operations using this key'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=100,
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
|
@ -24,7 +24,7 @@ class ClusterTypeSerializer(ValidatedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ClusterType
|
||||
fields = ['id', 'name', 'slug', 'cluster_count']
|
||||
fields = ['id', 'name', 'slug', 'description', 'cluster_count']
|
||||
|
||||
|
||||
class ClusterGroupSerializer(ValidatedModelSerializer):
|
||||
@ -32,7 +32,7 @@ class ClusterGroupSerializer(ValidatedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ClusterGroup
|
||||
fields = ['id', 'name', 'slug', 'cluster_count']
|
||||
fields = ['id', 'name', 'slug', 'description', 'cluster_count']
|
||||
|
||||
|
||||
class ClusterSerializer(TaggitSerializer, CustomFieldModelSerializer):
|
||||
|
@ -24,14 +24,14 @@ class ClusterTypeFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = ClusterType
|
||||
fields = ['id', 'name', 'slug']
|
||||
fields = ['id', 'name', 'slug', 'description']
|
||||
|
||||
|
||||
class ClusterGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = ClusterGroup
|
||||
fields = ['id', 'name', 'slug']
|
||||
fields = ['id', 'name', 'slug', 'description']
|
||||
|
||||
|
||||
class ClusterFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
||||
|
@ -31,7 +31,7 @@ class ClusterTypeForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = ClusterType
|
||||
fields = [
|
||||
'name', 'slug',
|
||||
'name', 'slug', 'description',
|
||||
]
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ class ClusterGroupForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = ClusterGroup
|
||||
fields = [
|
||||
'name', 'slug',
|
||||
'name', 'slug', 'description',
|
||||
]
|
||||
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-13 20:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('virtualization', '0013_deterministic_ordering'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='clustergroup',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='clustertype',
|
||||
name='description',
|
||||
field=models.CharField(blank=True, max_length=200),
|
||||
),
|
||||
]
|
@ -34,8 +34,12 @@ class ClusterType(ChangeLoggedModel):
|
||||
slug = models.SlugField(
|
||||
unique=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
csv_headers = ['name', 'slug']
|
||||
csv_headers = ['name', 'slug', 'description']
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
@ -50,6 +54,7 @@ class ClusterType(ChangeLoggedModel):
|
||||
return (
|
||||
self.name,
|
||||
self.slug,
|
||||
self.description,
|
||||
)
|
||||
|
||||
|
||||
@ -68,8 +73,12 @@ class ClusterGroup(ChangeLoggedModel):
|
||||
slug = models.SlugField(
|
||||
unique=True
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
csv_headers = ['name', 'slug']
|
||||
csv_headers = ['name', 'slug', 'description']
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
@ -84,6 +93,7 @@ class ClusterGroup(ChangeLoggedModel):
|
||||
return (
|
||||
self.name,
|
||||
self.slug,
|
||||
self.description,
|
||||
)
|
||||
|
||||
|
||||
|
@ -55,7 +55,7 @@ class ClusterTypeTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = ClusterType
|
||||
fields = ('pk', 'name', 'cluster_count', 'actions')
|
||||
fields = ('pk', 'name', 'cluster_count', 'description', 'actions')
|
||||
|
||||
|
||||
#
|
||||
@ -74,7 +74,7 @@ class ClusterGroupTable(BaseTable):
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = ClusterGroup
|
||||
fields = ('pk', 'name', 'cluster_count', 'actions')
|
||||
fields = ('pk', 'name', 'cluster_count', 'description', 'actions')
|
||||
|
||||
|
||||
#
|
||||
|
@ -15,9 +15,9 @@ class ClusterTypeTestCase(TestCase):
|
||||
def setUpTestData(cls):
|
||||
|
||||
cluster_types = (
|
||||
ClusterType(name='Cluster Type 1', slug='cluster-type-1'),
|
||||
ClusterType(name='Cluster Type 2', slug='cluster-type-2'),
|
||||
ClusterType(name='Cluster Type 3', slug='cluster-type-3'),
|
||||
ClusterType(name='Cluster Type 1', slug='cluster-type-1', description='A'),
|
||||
ClusterType(name='Cluster Type 2', slug='cluster-type-2', description='B'),
|
||||
ClusterType(name='Cluster Type 3', slug='cluster-type-3', description='C'),
|
||||
)
|
||||
ClusterType.objects.bulk_create(cluster_types)
|
||||
|
||||
@ -34,6 +34,10 @@ class ClusterTypeTestCase(TestCase):
|
||||
params = {'slug': ['cluster-type-1', 'cluster-type-2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
|
||||
class ClusterGroupTestCase(TestCase):
|
||||
queryset = ClusterGroup.objects.all()
|
||||
@ -43,9 +47,9 @@ class ClusterGroupTestCase(TestCase):
|
||||
def setUpTestData(cls):
|
||||
|
||||
cluster_groups = (
|
||||
ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'),
|
||||
ClusterGroup(name='Cluster Group 2', slug='cluster-group-2'),
|
||||
ClusterGroup(name='Cluster Group 3', slug='cluster-group-3'),
|
||||
ClusterGroup(name='Cluster Group 1', slug='cluster-group-1', description='A'),
|
||||
ClusterGroup(name='Cluster Group 2', slug='cluster-group-2', description='B'),
|
||||
ClusterGroup(name='Cluster Group 3', slug='cluster-group-3', description='C'),
|
||||
)
|
||||
ClusterGroup.objects.bulk_create(cluster_groups)
|
||||
|
||||
@ -62,6 +66,10 @@ class ClusterGroupTestCase(TestCase):
|
||||
params = {'slug': ['cluster-group-1', 'cluster-group-2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
|
||||
class ClusterTestCase(TestCase):
|
||||
queryset = Cluster.objects.all()
|
||||
|
@ -23,13 +23,14 @@ class ClusterGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
cls.form_data = {
|
||||
'name': 'Cluster Group X',
|
||||
'slug': 'cluster-group-x',
|
||||
'description': 'A new cluster group',
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"name,slug",
|
||||
"Cluster Group 4,cluster-group-4",
|
||||
"Cluster Group 5,cluster-group-5",
|
||||
"Cluster Group 6,cluster-group-6",
|
||||
"name,slug,description",
|
||||
"Cluster Group 4,cluster-group-4,Fourth cluster group",
|
||||
"Cluster Group 5,cluster-group-5,Fifth cluster group",
|
||||
"Cluster Group 6,cluster-group-6,Sixth cluster group",
|
||||
)
|
||||
|
||||
|
||||
@ -48,13 +49,14 @@ class ClusterTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
cls.form_data = {
|
||||
'name': 'Cluster Type X',
|
||||
'slug': 'cluster-type-x',
|
||||
'description': 'A new cluster type',
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"name,slug",
|
||||
"Cluster Type 4,cluster-type-4",
|
||||
"Cluster Type 5,cluster-type-5",
|
||||
"Cluster Type 6,cluster-type-6",
|
||||
"name,slug,description",
|
||||
"Cluster Type 4,cluster-type-4,Fourth cluster type",
|
||||
"Cluster Type 5,cluster-type-5,Fifth cluster type",
|
||||
"Cluster Type 6,cluster-type-6,Sixth cluster type",
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user