From ba514aceac778122049998c113e912d83b359d9b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 1 Mar 2024 15:04:02 -0500 Subject: [PATCH] Rename CustomLink.content_types to object_types & use ObjectType proxy --- netbox/extras/api/serializers.py | 4 ++-- netbox/extras/filtersets.py | 8 ++++---- netbox/extras/forms/bulk_import.py | 6 +++--- netbox/extras/forms/filtersets.py | 6 +++--- netbox/extras/forms/model_forms.py | 6 +++--- netbox/extras/graphql/types.py | 2 +- .../migrations/0111_rename_content_types.py | 13 +++++++++++++ netbox/extras/models/models.py | 4 ++-- netbox/extras/tables/tables.py | 16 ++++++++-------- netbox/extras/templatetags/custom_links.py | 6 +++--- netbox/extras/tests/test_api.py | 10 +++++----- netbox/extras/tests/test_filtersets.py | 10 +++++----- netbox/extras/tests/test_views.py | 10 +++++----- netbox/netbox/tables/tables.py | 2 +- netbox/templates/extras/customfield.html | 2 +- netbox/templates/extras/customlink.html | 2 +- 16 files changed, 60 insertions(+), 47 deletions(-) diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 370450712..fe66e2035 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -196,7 +196,7 @@ class CustomFieldChoiceSetSerializer(ValidatedModelSerializer): class CustomLinkSerializer(ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='extras-api:customlink-detail') - content_types = ContentTypeField( + object_types = ContentTypeField( queryset=ObjectType.objects.with_feature('custom_links'), many=True ) @@ -204,7 +204,7 @@ class CustomLinkSerializer(ValidatedModelSerializer): class Meta: model = CustomLink fields = [ - 'id', 'url', 'display', 'content_types', 'name', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', + 'id', 'url', 'display', 'object_types', 'name', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', 'button_class', 'new_window', 'created', 'last_updated', ] brief_fields = ('id', 'url', 'display', 'name') diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py index 290670f5c..dd378075a 100644 --- a/netbox/extras/filtersets.py +++ b/netbox/extras/filtersets.py @@ -190,15 +190,15 @@ class CustomLinkFilterSet(BaseFilterSet): method='search', label=_('Search'), ) - content_type_id = MultiValueNumberFilter( - field_name='content_types__id' + object_types_id = MultiValueNumberFilter( + field_name='object_types__id' ) - content_types = ContentTypeFilter() + object_types = ContentTypeFilter() class Meta: model = CustomLink fields = [ - 'id', 'content_types', 'name', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', 'new_window', + 'id', 'object_types', 'name', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', 'new_window', ] def search(self, queryset, name, value): diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index 1d1b27617..abe35e30c 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -111,8 +111,8 @@ class CustomFieldChoiceSetImportForm(CSVModelForm): class CustomLinkImportForm(CSVModelForm): - content_types = CSVMultipleContentTypeField( - label=_('Content types'), + object_types = CSVMultipleContentTypeField( + label=_('Object types'), queryset=ObjectType.objects.with_feature('custom_links'), help_text=_("One or more assigned object types") ) @@ -120,7 +120,7 @@ class CustomLinkImportForm(CSVModelForm): class Meta: model = CustomLink fields = ( - 'name', 'content_types', 'enabled', 'weight', 'group_name', 'button_class', 'new_window', 'link_text', + 'name', 'object_types', 'enabled', 'weight', 'group_name', 'button_class', 'new_window', 'link_text', 'link_url', ) diff --git a/netbox/extras/forms/filtersets.py b/netbox/extras/forms/filtersets.py index ccfeb8c1d..208f28725 100644 --- a/netbox/extras/forms/filtersets.py +++ b/netbox/extras/forms/filtersets.py @@ -108,10 +108,10 @@ class CustomFieldChoiceSetFilterForm(SavedFiltersMixin, FilterForm): class CustomLinkFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( (None, ('q', 'filter_id')), - (_('Attributes'), ('content_types', 'enabled', 'new_window', 'weight')), + (_('Attributes'), ('object_types', 'enabled', 'new_window', 'weight')), ) - content_types = ContentTypeMultipleChoiceField( - label=_('Content types'), + object_types = ContentTypeMultipleChoiceField( + label=_('Object types'), queryset=ObjectType.objects.with_feature('custom_links'), required=False ) diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py index 776265878..70f533013 100644 --- a/netbox/extras/forms/model_forms.py +++ b/netbox/extras/forms/model_forms.py @@ -122,13 +122,13 @@ class CustomFieldChoiceSetForm(forms.ModelForm): class CustomLinkForm(forms.ModelForm): - content_types = ContentTypeMultipleChoiceField( - label=_('Content types'), + object_types = ContentTypeMultipleChoiceField( + label=_('Object types'), queryset=ObjectType.objects.with_feature('custom_links') ) fieldsets = ( - (_('Custom Link'), ('name', 'content_types', 'weight', 'group_name', 'button_class', 'enabled', 'new_window')), + (_('Custom Link'), ('name', 'object_types', 'weight', 'group_name', 'button_class', 'enabled', 'new_window')), (_('Templates'), ('link_text', 'link_url')), ) diff --git a/netbox/extras/graphql/types.py b/netbox/extras/graphql/types.py index 643568eaa..e4cfd4be7 100644 --- a/netbox/extras/graphql/types.py +++ b/netbox/extras/graphql/types.py @@ -55,7 +55,7 @@ class CustomLinkType(ObjectType): class Meta: model = models.CustomLink - exclude = ('content_types', ) + exclude = ('object_types', ) filterset_class = filtersets.CustomLinkFilterSet diff --git a/netbox/extras/migrations/0111_rename_content_types.py b/netbox/extras/migrations/0111_rename_content_types.py index 2b7b2358a..dc3ec9fe6 100644 --- a/netbox/extras/migrations/0111_rename_content_types.py +++ b/netbox/extras/migrations/0111_rename_content_types.py @@ -10,6 +10,7 @@ class Migration(migrations.Migration): ] operations = [ + # Custom fields migrations.RenameField( model_name='customfield', old_name='content_types', @@ -25,4 +26,16 @@ class Migration(migrations.Migration): name='object_type', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='core.objecttype'), ), + + # Custom links + migrations.RenameField( + model_name='customlink', + old_name='content_types', + new_name='object_types', + ), + migrations.AlterField( + model_name='customlink', + name='object_types', + field=models.ManyToManyField(related_name='custom_links', to='core.objecttype'), + ), ] diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index 6b5a7c150..7439546fb 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -313,8 +313,8 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel): A custom link to an external representation of a NetBox object. The link text and URL fields accept Jinja2 template code to be rendered with an object as context. """ - content_types = models.ManyToManyField( - to='contenttypes.ContentType', + object_types = models.ManyToManyField( + to='core.ObjectType', related_name='custom_links', help_text=_('The object type(s) to which this link applies.') ) diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index 8482c5e24..7adbae178 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -40,8 +40,8 @@ class CustomFieldTable(NetBoxTable): verbose_name=_('Name'), linkify=True ) - content_types = columns.ContentTypesColumn( - verbose_name=_('Content Types') + object_types = columns.ContentTypesColumn( + verbose_name=_('Object Types') ) required = columns.BooleanColumn( verbose_name=_('Required') @@ -71,11 +71,11 @@ class CustomFieldTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = CustomField fields = ( - 'pk', 'id', 'name', 'content_types', 'label', 'type', 'group_name', 'required', 'default', 'description', + 'pk', 'id', 'name', 'object_types', 'label', 'type', 'group_name', 'required', 'default', 'description', 'search_weight', 'filter_logic', 'ui_visible', 'ui_editable', 'is_cloneable', 'weight', 'choice_set', 'choices', 'created', 'last_updated', ) - default_columns = ('pk', 'name', 'content_types', 'label', 'group_name', 'type', 'required', 'description') + default_columns = ('pk', 'name', 'object_types', 'label', 'group_name', 'type', 'required', 'description') class CustomFieldChoiceSetTable(NetBoxTable): @@ -115,8 +115,8 @@ class CustomLinkTable(NetBoxTable): verbose_name=_('Name'), linkify=True ) - content_types = columns.ContentTypesColumn( - verbose_name=_('Content Types'), + object_types = columns.ContentTypesColumn( + verbose_name=_('Object Types'), ) enabled = columns.BooleanColumn( verbose_name=_('Enabled'), @@ -128,10 +128,10 @@ class CustomLinkTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = CustomLink fields = ( - 'pk', 'id', 'name', 'content_types', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', + 'pk', 'id', 'name', 'object_types', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', 'button_class', 'new_window', 'created', 'last_updated', ) - default_columns = ('pk', 'name', 'content_types', 'enabled', 'group_name', 'button_class', 'new_window') + default_columns = ('pk', 'name', 'object_types', 'enabled', 'group_name', 'button_class', 'new_window') class ExportTemplateTable(NetBoxTable): diff --git a/netbox/extras/templatetags/custom_links.py b/netbox/extras/templatetags/custom_links.py index 5de95b607..31cd22815 100644 --- a/netbox/extras/templatetags/custom_links.py +++ b/netbox/extras/templatetags/custom_links.py @@ -1,7 +1,7 @@ from django import template -from django.contrib.contenttypes.models import ContentType from django.utils.safestring import mark_safe +from core.models import ObjectType from extras.models import CustomLink @@ -32,8 +32,8 @@ def custom_links(context, obj): """ Render all applicable links for the given object. """ - content_type = ContentType.objects.get_for_model(obj) - custom_links = CustomLink.objects.filter(content_types=content_type, enabled=True) + object_type = ObjectType.objects.get_for_model(obj) + custom_links = CustomLink.objects.filter(object_types=object_type, enabled=True) if not custom_links: return '' diff --git a/netbox/extras/tests/test_api.py b/netbox/extras/tests/test_api.py index 01bbb312f..ae592b528 100644 --- a/netbox/extras/tests/test_api.py +++ b/netbox/extras/tests/test_api.py @@ -273,21 +273,21 @@ class CustomLinkTest(APIViewTestCases.APIViewTestCase): brief_fields = ['display', 'id', 'name', 'url'] create_data = [ { - 'content_types': ['dcim.site'], + 'object_types': ['dcim.site'], 'name': 'Custom Link 4', 'enabled': True, 'link_text': 'Link 4', 'link_url': 'http://example.com/?4', }, { - 'content_types': ['dcim.site'], + 'object_types': ['dcim.site'], 'name': 'Custom Link 5', 'enabled': True, 'link_text': 'Link 5', 'link_url': 'http://example.com/?5', }, { - 'content_types': ['dcim.site'], + 'object_types': ['dcim.site'], 'name': 'Custom Link 6', 'enabled': False, 'link_text': 'Link 6', @@ -301,7 +301,7 @@ class CustomLinkTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): - site_ct = ContentType.objects.get_for_model(Site) + site_type = ObjectType.objects.get_for_model(Site) custom_links = ( CustomLink( @@ -325,7 +325,7 @@ class CustomLinkTest(APIViewTestCases.APIViewTestCase): ) CustomLink.objects.bulk_create(custom_links) for i, custom_link in enumerate(custom_links): - custom_link.content_types.set([site_ct]) + custom_link.object_types.set([site_type]) class SavedFilterTest(APIViewTestCases.APIViewTestCase): diff --git a/netbox/extras/tests/test_filtersets.py b/netbox/extras/tests/test_filtersets.py index 25263fe68..a23e11288 100644 --- a/netbox/extras/tests/test_filtersets.py +++ b/netbox/extras/tests/test_filtersets.py @@ -397,7 +397,7 @@ class CustomLinkTestCase(TestCase, BaseFilterSetTests): @classmethod def setUpTestData(cls): - content_types = ContentType.objects.filter(model__in=['site', 'rack', 'device']) + object_types = ObjectType.objects.filter(model__in=['site', 'rack', 'device']) custom_links = ( CustomLink( @@ -427,7 +427,7 @@ class CustomLinkTestCase(TestCase, BaseFilterSetTests): ) CustomLink.objects.bulk_create(custom_links) for i, custom_link in enumerate(custom_links): - custom_link.content_types.set([content_types[i]]) + custom_link.object_types.set([object_types[i]]) def test_q(self): params = {'q': 'Custom Link 1'} @@ -437,10 +437,10 @@ class CustomLinkTestCase(TestCase, BaseFilterSetTests): params = {'name': ['Custom Link 1', 'Custom Link 2']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - def test_content_types(self): - params = {'content_types': 'dcim.site'} + def test_object_types(self): + params = {'object_types': 'dcim.site'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - params = {'content_type_id': [ContentType.objects.get_for_model(Site).pk]} + params = {'object_types_id': [ContentType.objects.get_for_model(Site).pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_weight(self): diff --git a/netbox/extras/tests/test_views.py b/netbox/extras/tests/test_views.py index 699388c53..890cd59de 100644 --- a/netbox/extras/tests/test_views.py +++ b/netbox/extras/tests/test_views.py @@ -138,7 +138,7 @@ class CustomLinkTestCase(ViewTestCases.PrimaryObjectViewTestCase): @classmethod def setUpTestData(cls): - site_ct = ContentType.objects.get_for_model(Site) + site_type = ObjectType.objects.get_for_model(Site) custom_links = ( CustomLink(name='Custom Link 1', enabled=True, link_text='Link 1', link_url='http://example.com/?1'), CustomLink(name='Custom Link 2', enabled=True, link_text='Link 2', link_url='http://example.com/?2'), @@ -146,11 +146,11 @@ class CustomLinkTestCase(ViewTestCases.PrimaryObjectViewTestCase): ) CustomLink.objects.bulk_create(custom_links) for i, custom_link in enumerate(custom_links): - custom_link.content_types.set([site_ct]) + custom_link.object_types.set([site_type]) cls.form_data = { 'name': 'Custom Link X', - 'content_types': [site_ct.pk], + 'object_types': [site_type.pk], 'enabled': False, 'weight': 100, 'button_class': CustomLinkButtonClassChoices.DEFAULT, @@ -159,7 +159,7 @@ class CustomLinkTestCase(ViewTestCases.PrimaryObjectViewTestCase): } cls.csv_data = ( - "name,content_types,enabled,weight,button_class,link_text,link_url", + "name,object_types,enabled,weight,button_class,link_text,link_url", "Custom Link 4,dcim.site,True,100,blue,Link 4,http://exmaple.com/?4", "Custom Link 5,dcim.site,True,100,blue,Link 5,http://exmaple.com/?5", "Custom Link 6,dcim.site,False,100,blue,Link 6,http://exmaple.com/?6", @@ -652,7 +652,7 @@ class CustomLinkTest(TestCase): new_window=False ) customlink.save() - customlink.content_types.set([ContentType.objects.get_for_model(Site)]) + customlink.object_types.set([ObjectType.objects.get_for_model(Site)]) site = Site(name='Test Site', slug='test-site') site.save() diff --git a/netbox/netbox/tables/tables.py b/netbox/netbox/tables/tables.py index 597d73a16..afef74752 100644 --- a/netbox/netbox/tables/tables.py +++ b/netbox/netbox/tables/tables.py @@ -208,7 +208,7 @@ class NetBoxTable(BaseTable): extra_columns.extend([ (f'cf_{cf.name}', columns.CustomFieldColumn(cf)) for cf in custom_fields ]) - custom_links = CustomLink.objects.filter(content_types=object_type, enabled=True) + custom_links = CustomLink.objects.filter(object_types=object_type, enabled=True) extra_columns.extend([ (f'cl_{cl.name}', columns.CustomLinkColumn(cl)) for cl in custom_links ]) diff --git a/netbox/templates/extras/customfield.html b/netbox/templates/extras/customfield.html index ca6988152..ddc6b30f4 100644 --- a/netbox/templates/extras/customfield.html +++ b/netbox/templates/extras/customfield.html @@ -89,7 +89,7 @@
{% trans "Object Types" %}
- {% for ct in object.content_types.all %} + {% for ct in object.object_types.all %} diff --git a/netbox/templates/extras/customlink.html b/netbox/templates/extras/customlink.html index 492408396..0b9b068da 100644 --- a/netbox/templates/extras/customlink.html +++ b/netbox/templates/extras/customlink.html @@ -38,7 +38,7 @@
{% trans "Assigned Models" %}
{{ ct }}
- {% for ct in object.content_types.all %} + {% for ct in object.object_types.all %}
{{ ct }}