Closes: #18588: Relabel Service model to Application Service

Updates the `verbose_name` of the `Service` and `ServiceTemplate` models to "Application Service" and
"Application Service Template" respectively. This serves as the foundational change for relabeling
the model throughout the user interface to reduce ambiguity.

To preserve backward compatibility for the REST and GraphQL APIs, the test suites have been updated
to assert the stability of the original field and parameter names. This includes:

*   Using `filter_name_map` in the filterset test case to ensure API query parameters remain
    `service` and `service_id`.
*   Employing the GraphQL test suite's aliasing mechanism to ensure the public schema remains
    unchanged despite the underlying `verbose_name` modification.

Subsequent commits will address UI-specific labels in navigation, tables, forms, and templates.
This commit is contained in:
Jason Novinger 2025-07-16 13:49:53 -05:00
parent 5f8a4f6c43
commit a97a4e9f23
4 changed files with 22 additions and 9 deletions

View File

@ -55,8 +55,8 @@ class ServiceTemplate(ServiceBase, PrimaryModel):
class Meta:
ordering = ('name',)
verbose_name = _('service template')
verbose_name_plural = _('service templates')
verbose_name = _('application service template')
verbose_name_plural = _('application service templates')
class Service(ContactsMixin, ServiceBase, PrimaryModel):
@ -94,5 +94,5 @@ class Service(ContactsMixin, ServiceBase, PrimaryModel):
models.Index(fields=('parent_object_type', 'parent_object_id')),
)
ordering = ('protocol', 'ports', 'pk') # (protocol, port) may be non-unique
verbose_name = _('service')
verbose_name_plural = _('services')
verbose_name = _('application service')
verbose_name_plural = _('application services')

View File

@ -1162,6 +1162,7 @@ class ServiceTemplateTest(APIViewTestCases.APIViewTestCase):
bulk_update_data = {
'description': 'New description',
}
graphql_base_name = 'service_template'
@classmethod
def setUpTestData(cls):
@ -1197,6 +1198,7 @@ class ServiceTest(APIViewTestCases.APIViewTestCase):
bulk_update_data = {
'description': 'New description',
}
graphql_base_name = 'service'
@classmethod
def setUpTestData(cls):

View File

@ -1101,6 +1101,9 @@ class IPAddressTestCase(TestCase, ChangeLoggedFilterSetTests):
queryset = IPAddress.objects.all()
filterset = IPAddressFilterSet
ignore_fields = ('fhrpgroup',)
filter_name_map = {
'application_service': 'service',
}
@classmethod
def setUpTestData(cls):

View File

@ -33,6 +33,7 @@ class BaseFilterSetTests:
queryset = None
filterset = None
ignore_fields = tuple()
filter_name_map = {}
def get_m2m_filter_name(self, field):
"""
@ -46,7 +47,13 @@ class BaseFilterSetTests:
"""
Given a model field, return an iterable of (name, class) for each filter that should be defined on
the model's FilterSet class. If the appropriate filter class cannot be determined, it will be None.
filter_name_map provides a mechanism for developers to provide an actual field name for the
filter that is being resolved, given the field's actual name.
"""
# If an alias is not present in filter_name_map, then use field.name
filter_name = self.filter_name_map.get(field.name, field.name)
# ForeignKey & OneToOneField
if issubclass(field.__class__, ForeignKey) or type(field) is OneToOneRel:
@ -57,19 +64,20 @@ class BaseFilterSetTests:
# ForeignKeys to ObjectType need two filters: 'app.model' & PK
if field.related_model is ObjectType:
return [
(field.name, ContentTypeFilter),
(f'{field.name}_id', django_filters.ModelMultipleChoiceFilter),
(filter_name, ContentTypeFilter),
(f'{filter_name}_id', django_filters.ModelMultipleChoiceFilter),
]
# ForeignKey to an MPTT-enabled model
if issubclass(field.related_model, MPTTModel) and field.model is not field.related_model:
return [(f'{field.name}_id', TreeNodeMultipleChoiceFilter)]
return [(f'{filter_name}_id', TreeNodeMultipleChoiceFilter)]
return [(f'{field.name}_id', django_filters.ModelMultipleChoiceFilter)]
return [(f'{filter_name}_id', django_filters.ModelMultipleChoiceFilter)]
# Many-to-many relationships (forward & backward)
elif type(field) in (ManyToManyField, ManyToManyRel):
filter_name = self.get_m2m_filter_name(field)
filter_name = self.filter_name_map.get(filter_name, filter_name)
# ManyToManyFields to ObjectType need two filters: 'app.model' & PK
if field.related_model is ObjectType:
@ -85,7 +93,7 @@ class BaseFilterSetTests:
return [('tag', TagFilter)]
# Unable to determine the correct filter class
return [(field.name, None)]
return [(filter_name, None)]
def test_id(self):
"""