17058 RackType name -> model (#17059)

* 17058 RackType name -> model

* 17058 RackType name -> model

* 17058 fix tests

* 17058 fix tests
This commit is contained in:
Arthur Hanson 2024-08-01 20:06:51 +07:00 committed by GitHub
parent c51e91dddd
commit d6f2fc7d29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 74 additions and 59 deletions

View File

@ -10,9 +10,13 @@ A rack type defines the physical characteristics of a particular model of [rack]
The [manufacturer](./manufacturer.md) which produces this type of rack. The [manufacturer](./manufacturer.md) which produces this type of rack.
### Name ### Model
The unique name of the rack type. The model number assigned to this rack type by its manufacturer. Must be unique to the manufacturer.
### Slug
A unique URL-friendly representation of the model identifier. (This value can be used for filtering.)
### Form Factor ### Form Factor

View File

@ -73,12 +73,12 @@ class RackTypeSerializer(RackBaseSerializer):
class Meta: class Meta:
model = RackType model = RackType
fields = [ fields = [
'id', 'url', 'display_url', 'display', 'manufacturer', 'name', 'slug', 'description', 'form_factor', 'id', 'url', 'display_url', 'display', 'manufacturer', 'model', 'slug', 'description', 'form_factor',
'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'weight', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'weight',
'max_weight', 'weight_unit', 'mounting_depth', 'airflow', 'description', 'comments', 'tags', 'max_weight', 'weight_unit', 'mounting_depth', 'airflow', 'description', 'comments', 'tags',
'custom_fields', 'created', 'last_updated', 'custom_fields', 'created', 'last_updated',
] ]
brief_fields = ('id', 'url', 'display', 'manufacturer', 'name', 'slug', 'description') brief_fields = ('id', 'url', 'display', 'manufacturer', 'model', 'slug', 'description')
class RackSerializer(RackBaseSerializer): class RackSerializer(RackBaseSerializer):

View File

@ -311,7 +311,7 @@ class RackTypeFilterSet(NetBoxModelFilterSet):
class Meta: class Meta:
model = RackType model = RackType
fields = ( fields = (
'id', 'name', 'slug', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'id', 'model', 'slug', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit',
'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', 'description', 'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit', 'description',
) )
@ -319,7 +319,7 @@ class RackTypeFilterSet(NetBoxModelFilterSet):
if not value.strip(): if not value.strip():
return queryset return queryset
return queryset.filter( return queryset.filter(
Q(name__icontains=value) | Q(model__icontains=value) |
Q(description__icontains=value) | Q(description__icontains=value) |
Q(comments__icontains=value) Q(comments__icontains=value)
) )

View File

@ -222,7 +222,7 @@ class RackTypeImportForm(NetBoxModelImportForm):
class Meta: class Meta:
model = RackType model = RackType
fields = ( fields = (
'manufacturer', 'name', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'manufacturer', 'model', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units',
'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', 'weight', 'max_weight', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', 'weight', 'max_weight',
'weight_unit', 'description', 'comments', 'tags', 'weight_unit', 'description', 'comments', 'tags',
) )

View File

@ -208,10 +208,13 @@ class RackTypeForm(NetBoxModelForm):
queryset=Manufacturer.objects.all() queryset=Manufacturer.objects.all()
) )
comments = CommentField() comments = CommentField()
slug = SlugField() slug = SlugField(
label=_('Slug'),
slug_source='model'
)
fieldsets = ( fieldsets = (
FieldSet('manufacturer', 'name', 'slug', 'description', 'form_factor', 'airflow', 'tags', name=_('Rack Type')), FieldSet('manufacturer', 'model', 'slug', 'description', 'form_factor', 'airflow', 'tags', name=_('Rack Type')),
FieldSet( FieldSet(
'width', 'u_height', 'width', 'u_height',
InlineFields('outer_width', 'outer_depth', 'outer_unit', label=_('Outer Dimensions')), InlineFields('outer_width', 'outer_depth', 'outer_unit', label=_('Outer Dimensions')),
@ -224,7 +227,7 @@ class RackTypeForm(NetBoxModelForm):
class Meta: class Meta:
model = RackType model = RackType
fields = [ fields = [
'manufacturer', 'name', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'manufacturer', 'model', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units',
'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit',
'airflow', 'description', 'comments', 'tags', 'airflow', 'description', 'comments', 'tags',
] ]

View File

@ -613,7 +613,6 @@ class PowerPortTemplateType(ModularComponentTemplateType):
filters=RackTypeFilter filters=RackTypeFilter
) )
class RackTypeType(NetBoxObjectType): class RackTypeType(NetBoxObjectType):
_name: str
manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')] manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')]

View File

@ -37,14 +37,7 @@ class Migration(migrations.Migration):
related_name='rack_types', related_name='rack_types',
to='dcim.manufacturer' to='dcim.manufacturer'
)), )),
('name', models.CharField(max_length=100)), ('model', models.CharField(max_length=100)),
('_name', utilities.fields.NaturalOrderingField(
'name',
blank=True,
max_length=100,
naturalize_function=utilities.ordering.naturalize
),
),
('slug', models.SlugField(max_length=100, unique=True)), ('slug', models.SlugField(max_length=100, unique=True)),
('form_factor', models.CharField(blank=True, max_length=50)), ('form_factor', models.CharField(blank=True, max_length=50)),
('width', models.PositiveSmallIntegerField(default=19)), ('width', models.PositiveSmallIntegerField(default=19)),
@ -71,7 +64,7 @@ class Migration(migrations.Migration):
options={ options={
'verbose_name': 'racktype', 'verbose_name': 'racktype',
'verbose_name_plural': 'racktypes', 'verbose_name_plural': 'racktypes',
'ordering': ('_name', 'pk'), 'ordering': ('manufacturer', 'model'),
}, },
), ),
migrations.RenameField( migrations.RenameField(
@ -90,4 +83,16 @@ class Migration(migrations.Migration):
to='dcim.racktype', to='dcim.racktype',
), ),
), ),
migrations.AddConstraint(
model_name='racktype',
constraint=models.UniqueConstraint(
fields=('manufacturer', 'model'), name='dcim_racktype_unique_manufacturer_model'
),
),
migrations.AddConstraint(
model_name='racktype',
constraint=models.UniqueConstraint(
fields=('manufacturer', 'slug'), name='dcim_racktype_unique_manufacturer_slug'
),
),
] ]

View File

@ -136,15 +136,10 @@ class RackType(RackBase):
on_delete=models.PROTECT, on_delete=models.PROTECT,
related_name='rack_types' related_name='rack_types'
) )
name = models.CharField( model = models.CharField(
verbose_name=_('name'), verbose_name=_('model'),
max_length=100 max_length=100
) )
_name = NaturalOrderingField(
target_field='name',
max_length=100,
blank=True
)
slug = models.SlugField( slug = models.SlugField(
verbose_name=_('slug'), verbose_name=_('slug'),
max_length=100, max_length=100,
@ -160,19 +155,29 @@ class RackType(RackBase):
) )
class Meta: class Meta:
ordering = ('_name', 'pk') # (site, location, name) may be non-unique ordering = ('manufacturer', 'model')
constraints = (
models.UniqueConstraint(
fields=('manufacturer', 'model'),
name='%(app_label)s_%(class)s_unique_manufacturer_model'
),
models.UniqueConstraint(
fields=('manufacturer', 'slug'),
name='%(app_label)s_%(class)s_unique_manufacturer_slug'
),
)
verbose_name = _('rack type') verbose_name = _('rack type')
verbose_name_plural = _('rack types') verbose_name_plural = _('rack types')
def __str__(self): def __str__(self):
return self.name return self.model
def get_absolute_url(self): def get_absolute_url(self):
return reverse('dcim:racktype', args=[self.pk]) return reverse('dcim:racktype', args=[self.pk])
@property @property
def full_name(self): def full_name(self):
return f"{self.manufacturer} {self.name}" return f"{self.manufacturer} {self.model}"
def clean(self): def clean(self):
super().clean() super().clean()

View File

@ -246,7 +246,7 @@ class PowerPortIndex(SearchIndex):
class RackTypeIndex(SearchIndex): class RackTypeIndex(SearchIndex):
model = models.RackType model = models.RackType
fields = ( fields = (
('name', 100), ('model', 100),
('description', 500), ('description', 500),
('comments', 5000), ('comments', 5000),
) )

View File

@ -50,9 +50,8 @@ class RackRoleTable(NetBoxTable):
# #
class RackTypeTable(NetBoxTable): class RackTypeTable(NetBoxTable):
name = tables.Column( model = tables.Column(
verbose_name=_('Name'), verbose_name=_('Model'),
order_by=('_name',),
linkify=True linkify=True
) )
manufacturer = tables.Column( manufacturer = tables.Column(
@ -96,12 +95,12 @@ class RackTypeTable(NetBoxTable):
class Meta(NetBoxTable.Meta): class Meta(NetBoxTable.Meta):
model = RackType model = RackType
fields = ( fields = (
'pk', 'id', 'name', 'manufacturer', 'form_factor', 'u_height', 'starting_unit', 'width', 'outer_width', 'pk', 'id', 'model', 'manufacturer', 'form_factor', 'u_height', 'starting_unit', 'width', 'outer_width',
'outer_depth', 'mounting_depth', 'airflow', 'weight', 'max_weight', 'description', 'comments', 'outer_depth', 'mounting_depth', 'airflow', 'weight', 'max_weight', 'description', 'comments',
'instance_count', 'tags', 'created', 'last_updated', 'instance_count', 'tags', 'created', 'last_updated',
) )
default_columns = ( default_columns = (
'pk', 'name', 'manufacturer', 'type', 'u_height', 'description', 'instance_count', 'pk', 'model', 'manufacturer', 'type', 'u_height', 'description', 'instance_count',
) )

View File

@ -273,7 +273,7 @@ class RackRoleTest(APIViewTestCases.APIViewTestCase):
class RackTypeTest(APIViewTestCases.APIViewTestCase): class RackTypeTest(APIViewTestCases.APIViewTestCase):
model = RackType model = RackType
brief_fields = ['description', 'display', 'id', 'manufacturer', 'name', 'slug', 'url'] brief_fields = ['description', 'display', 'id', 'manufacturer', 'model', 'slug', 'url']
bulk_update_data = { bulk_update_data = {
'description': 'new description', 'description': 'new description',
} }
@ -287,26 +287,26 @@ class RackTypeTest(APIViewTestCases.APIViewTestCase):
Manufacturer.objects.bulk_create(manufacturers) Manufacturer.objects.bulk_create(manufacturers)
rack_types = ( rack_types = (
RackType(manufacturer=manufacturers[0], name='Rack Type 1', slug='rack-type-1'), RackType(manufacturer=manufacturers[0], model='Rack Type 1', slug='rack-type-1'),
RackType(manufacturer=manufacturers[0], name='Rack Type 2', slug='rack-type-2'), RackType(manufacturer=manufacturers[0], model='Rack Type 2', slug='rack-type-2'),
RackType(manufacturer=manufacturers[0], name='Rack Type 3', slug='rack-type-3'), RackType(manufacturer=manufacturers[0], model='Rack Type 3', slug='rack-type-3'),
) )
RackType.objects.bulk_create(rack_types) RackType.objects.bulk_create(rack_types)
cls.create_data = [ cls.create_data = [
{ {
'manufacturer': manufacturers[1].pk, 'manufacturer': manufacturers[1].pk,
'name': 'Rack Type 4', 'model': 'Rack Type 4',
'slug': 'rack-type-4', 'slug': 'rack-type-4',
}, },
{ {
'manufacturer': manufacturers[1].pk, 'manufacturer': manufacturers[1].pk,
'name': 'Rack Type 5', 'model': 'Rack Type 5',
'slug': 'rack-type-5', 'slug': 'rack-type-5',
}, },
{ {
'manufacturer': manufacturers[1].pk, 'manufacturer': manufacturers[1].pk,
'name': 'Rack Type 6', 'model': 'Rack Type 6',
'slug': 'rack-type-6', 'slug': 'rack-type-6',
}, },
] ]

View File

@ -482,7 +482,7 @@ class RackTypeTestCase(TestCase, ChangeLoggedFilterSetTests):
racks = ( racks = (
RackType( RackType(
manufacturer=manufacturers[0], manufacturer=manufacturers[0],
name='RackType 1', model='RackType 1',
slug='rack-type-1', slug='rack-type-1',
form_factor=RackFormFactorChoices.TYPE_2POST, form_factor=RackFormFactorChoices.TYPE_2POST,
width=RackWidthChoices.WIDTH_19IN, width=RackWidthChoices.WIDTH_19IN,
@ -500,7 +500,7 @@ class RackTypeTestCase(TestCase, ChangeLoggedFilterSetTests):
), ),
RackType( RackType(
manufacturer=manufacturers[1], manufacturer=manufacturers[1],
name='RackType 2', model='RackType 2',
slug='rack-type-2', slug='rack-type-2',
form_factor=RackFormFactorChoices.TYPE_4POST, form_factor=RackFormFactorChoices.TYPE_4POST,
width=RackWidthChoices.WIDTH_21IN, width=RackWidthChoices.WIDTH_21IN,
@ -518,7 +518,7 @@ class RackTypeTestCase(TestCase, ChangeLoggedFilterSetTests):
), ),
RackType( RackType(
manufacturer=manufacturers[2], manufacturer=manufacturers[2],
name='RackType 3', model='RackType 3',
slug='rack-type-3', slug='rack-type-3',
form_factor=RackFormFactorChoices.TYPE_CABINET, form_factor=RackFormFactorChoices.TYPE_CABINET,
width=RackWidthChoices.WIDTH_23IN, width=RackWidthChoices.WIDTH_23IN,
@ -548,8 +548,8 @@ class RackTypeTestCase(TestCase, ChangeLoggedFilterSetTests):
params = {'manufacturer': [manufacturers[0].slug, manufacturers[1].slug]} params = {'manufacturer': [manufacturers[0].slug, manufacturers[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_name(self): def test_model(self):
params = {'name': ['RackType 1', 'RackType 2']} params = {'model': ['RackType 1', 'RackType 2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_slug(self): def test_slug(self):
@ -661,7 +661,7 @@ class RackTestCase(TestCase, ChangeLoggedFilterSetTests):
rack_types = ( rack_types = (
RackType( RackType(
manufacturer=manufacturers[0], manufacturer=manufacturers[0],
name='RackType 1', model='RackType 1',
slug='rack-type-1', slug='rack-type-1',
form_factor=RackFormFactorChoices.TYPE_2POST, form_factor=RackFormFactorChoices.TYPE_2POST,
width=RackWidthChoices.WIDTH_19IN, width=RackWidthChoices.WIDTH_19IN,
@ -679,7 +679,7 @@ class RackTestCase(TestCase, ChangeLoggedFilterSetTests):
), ),
RackType( RackType(
manufacturer=manufacturers[1], manufacturer=manufacturers[1],
name='RackType 2', model='RackType 2',
slug='rack-type-2', slug='rack-type-2',
form_factor=RackFormFactorChoices.TYPE_4POST, form_factor=RackFormFactorChoices.TYPE_4POST,
width=RackWidthChoices.WIDTH_21IN, width=RackWidthChoices.WIDTH_21IN,

View File

@ -82,7 +82,7 @@ class RackTypeTestCase(TestCase):
RackType.objects.create( RackType.objects.create(
manufacturer=manufacturer, manufacturer=manufacturer,
name='RackType 1', model='RackType 1',
slug='rack-type-1', slug='rack-type-1',
width=11, width=11,
u_height=22, u_height=22,

View File

@ -346,9 +346,9 @@ class RackTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
Manufacturer.objects.bulk_create(manufacturers) Manufacturer.objects.bulk_create(manufacturers)
rack_types = ( rack_types = (
RackType(manufacturer=manufacturers[0], name='RackType 1', slug='rack-type-1',), RackType(manufacturer=manufacturers[0], model='RackType 1', slug='rack-type-1',),
RackType(manufacturer=manufacturers[0], name='RackType 2', slug='rack-type-2',), RackType(manufacturer=manufacturers[0], model='RackType 2', slug='rack-type-2',),
RackType(manufacturer=manufacturers[0], name='RackType 3', slug='rack-type-3',), RackType(manufacturer=manufacturers[0], model='RackType 3', slug='rack-type-3',),
) )
RackType.objects.bulk_create(rack_types) RackType.objects.bulk_create(rack_types)
@ -356,7 +356,7 @@ class RackTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
cls.form_data = { cls.form_data = {
'manufacturer': manufacturers[1].pk, 'manufacturer': manufacturers[1].pk,
'name': 'RackType X', 'model': 'RackType X',
'slug': 'rack-type-x', 'slug': 'rack-type-x',
'type': RackFormFactorChoices.TYPE_CABINET, 'type': RackFormFactorChoices.TYPE_CABINET,
'width': RackWidthChoices.WIDTH_19IN, 'width': RackWidthChoices.WIDTH_19IN,
@ -374,14 +374,14 @@ class RackTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
} }
cls.csv_data = ( cls.csv_data = (
"manufacturer,name,slug,width,u_height,weight,max_weight,weight_unit", "manufacturer,model,slug,width,u_height,weight,max_weight,weight_unit",
"Manufacturer 1,RackType 4,rack-type-4,19,42,100,2000,kg", "Manufacturer 1,RackType 4,rack-type-4,19,42,100,2000,kg",
"Manufacturer 1,RackType 5,rack-type-5,19,42,100,2000,kg", "Manufacturer 1,RackType 5,rack-type-5,19,42,100,2000,kg",
"Manufacturer 1,RackType 6,rack-type-6,19,42,100,2000,kg", "Manufacturer 1,RackType 6,rack-type-6,19,42,100,2000,kg",
) )
cls.csv_update_data = ( cls.csv_update_data = (
"id,name", "id,model",
f"{rack_types[0].pk},RackType 7", f"{rack_types[0].pk},RackType 7",
f"{rack_types[1].pk},RackType 8", f"{rack_types[1].pk},RackType 8",
f"{rack_types[2].pk},RackType 9", f"{rack_types[2].pk},RackType 9",

View File

@ -17,8 +17,8 @@
<td>{{ object.manufacturer|linkify }}</td> <td>{{ object.manufacturer|linkify }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Name" %}</th> <th scope="row">{% trans "Model" %}</th>
<td>{{ object.name }}</td> <td>{{ object.model }}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{% trans "Description" %}</th> <th scope="row">{% trans "Description" %}</th>