From 143f3cc27c47aa3175320567052151548e69c992 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 14 Oct 2020 15:23:23 -0400 Subject: [PATCH] #4711: Rename CustomField.obj_type to content_types --- netbox/extras/admin.py | 8 ++++---- netbox/extras/api/customfields.py | 6 +++--- netbox/extras/filters.py | 3 +-- netbox/extras/forms.py | 8 ++++---- ...choices.py => 0050_customfield_changes.py} | 6 ++++++ .../migrations/0051_migrate_customfields.py | 2 +- netbox/extras/models/customfields.py | 4 ++-- netbox/extras/models/models.py | 2 +- netbox/extras/signals.py | 4 ++-- netbox/extras/tests/test_changelog.py | 4 ++-- netbox/extras/tests/test_customfields.py | 20 +++++++++---------- netbox/utilities/tests/test_api.py | 2 +- 12 files changed, 37 insertions(+), 32 deletions(-) rename netbox/extras/migrations/{0050_customfield_add_choices.py => 0050_customfield_changes.py} (84%) diff --git a/netbox/extras/admin.py b/netbox/extras/admin.py index a8b4c0eb8..1b2fe3d12 100644 --- a/netbox/extras/admin.py +++ b/netbox/extras/admin.py @@ -79,7 +79,7 @@ class CustomFieldForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - order_content_types(self.fields['obj_type']) + order_content_types(self.fields['content_types']) def clean(self): @@ -98,7 +98,7 @@ class CustomFieldAdmin(admin.ModelAdmin): 'name', 'models', 'type', 'required', 'filter_logic', 'default', 'weight', 'description', ] list_filter = [ - 'type', 'required', 'obj_type', + 'type', 'required', 'content_types', ] fieldsets = ( ('Custom Field', { @@ -106,7 +106,7 @@ class CustomFieldAdmin(admin.ModelAdmin): }), ('Assignment', { 'description': 'A custom field must be assigned to one or more object types.', - 'fields': ('obj_type',) + 'fields': ('content_types',) }), ('Choices', { 'description': 'A selection field must have two or more choices assigned to it.', @@ -115,7 +115,7 @@ class CustomFieldAdmin(admin.ModelAdmin): ) def models(self, obj): - return ', '.join([ct.name for ct in obj.obj_type.all()]) + return ', '.join([ct.name for ct in obj.content_types.all()]) # diff --git a/netbox/extras/api/customfields.py b/netbox/extras/api/customfields.py index a5f11fde6..d17090fc2 100644 --- a/netbox/extras/api/customfields.py +++ b/netbox/extras/api/customfields.py @@ -24,7 +24,7 @@ class CustomFieldDefaultValues: # Retrieve the CustomFields for the parent model content_type = ContentType.objects.get_for_model(self.model) - fields = CustomField.objects.filter(obj_type=content_type) + fields = CustomField.objects.filter(content_types=content_type) # Populate the default value for each CustomField value = {} @@ -52,7 +52,7 @@ class CustomFieldsDataField(Field): """ if not hasattr(self, '_custom_fields'): content_type = ContentType.objects.get_for_model(self.parent.Meta.model) - self._custom_fields = CustomField.objects.filter(obj_type=content_type) + self._custom_fields = CustomField.objects.filter(content_types=content_type) return self._custom_fields def to_representation(self, obj): @@ -132,7 +132,7 @@ class CustomFieldModelSerializer(ValidatedModelSerializer): # Retrieve the set of CustomFields which apply to this type of object content_type = ContentType.objects.get_for_model(self.Meta.model) - fields = CustomField.objects.filter(obj_type=content_type) + fields = CustomField.objects.filter(content_types=content_type) # Populate CustomFieldValues for each instance from database if type(self.instance) in (list, tuple): diff --git a/netbox/extras/filters.py b/netbox/extras/filters.py index 91f4d333b..d36ab28ad 100644 --- a/netbox/extras/filters.py +++ b/netbox/extras/filters.py @@ -65,9 +65,8 @@ class CustomFieldFilterSet(django_filters.FilterSet): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - obj_type = ContentType.objects.get_for_model(self._meta.model) custom_fields = CustomField.objects.filter( - obj_type=obj_type + content_types=ContentType.objects.get_for_model(self._meta.model) ).exclude( filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED ) diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index d09ff64fe..eee54076b 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -35,7 +35,7 @@ class CustomFieldModelForm(forms.ModelForm): Append form fields for all CustomFields assigned to this model. """ # Append form fields; assign initial values if modifying and existing object - for cf in CustomField.objects.filter(obj_type=self.obj_type): + for cf in CustomField.objects.filter(content_types=self.obj_type): field_name = 'cf_{}'.format(cf.name) if self.instance.pk: self.fields[field_name] = cf.to_form_field(set_initial=False) @@ -60,7 +60,7 @@ class CustomFieldModelCSVForm(CSVModelForm, CustomFieldModelForm): def _append_customfield_fields(self): # Append form fields - for cf in CustomField.objects.filter(obj_type=self.obj_type): + for cf in CustomField.objects.filter(content_types=self.obj_type): field_name = 'cf_{}'.format(cf.name) self.fields[field_name] = cf.to_form_field(for_csv_import=True) @@ -77,7 +77,7 @@ class CustomFieldBulkEditForm(BulkEditForm): self.obj_type = ContentType.objects.get_for_model(self.model) # Add all applicable CustomFields to the form - custom_fields = CustomField.objects.filter(obj_type=self.obj_type) + custom_fields = CustomField.objects.filter(content_types=self.obj_type) for cf in custom_fields: # Annotate non-required custom fields as nullable if not cf.required: @@ -96,7 +96,7 @@ class CustomFieldFilterForm(forms.Form): super().__init__(*args, **kwargs) # Add all applicable CustomFields to the form - custom_fields = CustomField.objects.filter(obj_type=self.obj_type).exclude( + custom_fields = CustomField.objects.filter(content_types=self.obj_type).exclude( filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED ) for cf in custom_fields: diff --git a/netbox/extras/migrations/0050_customfield_add_choices.py b/netbox/extras/migrations/0050_customfield_changes.py similarity index 84% rename from netbox/extras/migrations/0050_customfield_add_choices.py rename to netbox/extras/migrations/0050_customfield_changes.py index 1ae63a2c3..923b5dbc4 100644 --- a/netbox/extras/migrations/0050_customfield_add_choices.py +++ b/netbox/extras/migrations/0050_customfield_changes.py @@ -32,4 +32,10 @@ class Migration(migrations.Migration): size=None ), ), + # Rename obj_type to content_types + migrations.RenameField( + model_name='customfield', + old_name='obj_type', + new_name='content_types', + ), ] diff --git a/netbox/extras/migrations/0051_migrate_customfields.py b/netbox/extras/migrations/0051_migrate_customfields.py index ac6d3816f..e4bcef1b3 100644 --- a/netbox/extras/migrations/0051_migrate_customfields.py +++ b/netbox/extras/migrations/0051_migrate_customfields.py @@ -56,7 +56,7 @@ class Migration(migrations.Migration): dependencies = [ ('circuits', '0020_custom_field_data'), ('dcim', '0117_custom_field_data'), - ('extras', '0050_customfield_add_choices'), + ('extras', '0050_customfield_changes'), ('ipam', '0038_custom_field_data'), ('secrets', '0010_custom_field_data'), ('tenancy', '0010_custom_field_data'), diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index 73fc6a2e3..62912ee2c 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -50,11 +50,11 @@ class CustomFieldManager(models.Manager): Return all CustomFields assigned to the given model. """ content_type = ContentType.objects.get_for_model(model._meta.concrete_model) - return self.get_queryset().filter(obj_type=content_type) + return self.get_queryset().filter(content_types=content_type) class CustomField(models.Model): - obj_type = models.ManyToManyField( + content_types = models.ManyToManyField( to=ContentType, related_name='custom_fields', verbose_name='Object(s)', diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index 8c88bb1da..065f517f5 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -8,7 +8,6 @@ from django.contrib.contenttypes.models import ContentType from django.core.validators import ValidationError from django.db import models from django.http import HttpResponse -from django.template import Template, Context from django.urls import reverse from django.utils import timezone from rest_framework.utils.encoders import JSONEncoder @@ -32,6 +31,7 @@ class Webhook(models.Model): delete in NetBox. The request will contain a representation of the object, which the remote application can act on. Each Webhook can be limited to firing only on certain actions or certain object types. """ + # TODO: Rename obj_type to content_types (see #4711) obj_type = models.ManyToManyField( to=ContentType, related_name='webhooks', diff --git a/netbox/extras/signals.py b/netbox/extras/signals.py index d4e187b5c..0d6295e5b 100644 --- a/netbox/extras/signals.py +++ b/netbox/extras/signals.py @@ -89,10 +89,10 @@ def handle_cf_deleted(instance, **kwargs): """ Handle the cleanup of old custom field data when a CustomField is deleted. """ - instance.remove_stale_data(instance.obj_type.all()) + instance.remove_stale_data(instance.content_types.all()) -m2m_changed.connect(handle_cf_removed_obj_types, sender=CustomField.obj_type.through) +m2m_changed.connect(handle_cf_removed_obj_types, sender=CustomField.content_types.through) pre_delete.connect(handle_cf_deleted, sender=CustomField) diff --git a/netbox/extras/tests/test_changelog.py b/netbox/extras/tests/test_changelog.py index 5d1dee864..dbdbb5343 100644 --- a/netbox/extras/tests/test_changelog.py +++ b/netbox/extras/tests/test_changelog.py @@ -25,7 +25,7 @@ class ChangeLogViewTest(ModelViewTestCase): required=False ) cf.save() - cf.obj_type.set([ct]) + cf.content_types.set([ct]) def test_create_object(self): tags = self.create_tags('Tag 1', 'Tag 2') @@ -131,7 +131,7 @@ class ChangeLogAPITest(APITestCase): required=False ) cf.save() - cf.obj_type.set([ct]) + cf.content_types.set([ct]) # Create some tags tags = ( diff --git a/netbox/extras/tests/test_customfields.py b/netbox/extras/tests/test_customfields.py index 38d904d41..7ebb7701e 100644 --- a/netbox/extras/tests/test_customfields.py +++ b/netbox/extras/tests/test_customfields.py @@ -39,7 +39,7 @@ class CustomFieldTest(TestCase): # Create a custom field cf = CustomField(type=data['field_type'], name='my_field', required=False) cf.save() - cf.obj_type.set([obj_type]) + cf.content_types.set([obj_type]) cf.save() # Assign a value to the first Site @@ -72,7 +72,7 @@ class CustomFieldTest(TestCase): choices=['Option A', 'Option B', 'Option C'] ) cf.save() - cf.obj_type.set([obj_type]) + cf.content_types.set([obj_type]) cf.save() # Assign a value to the first Site @@ -100,7 +100,7 @@ class CustomFieldManagerTest(TestCase): content_type = ContentType.objects.get_for_model(Site) custom_field = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='text_field', default='foo') custom_field.save() - custom_field.obj_type.set([content_type]) + custom_field.content_types.set([content_type]) def test_get_for_model(self): self.assertEqual(CustomField.objects.get_for_model(Site).count(), 1) @@ -116,33 +116,33 @@ class CustomFieldAPITest(APITestCase): # Text custom field cls.cf_text = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='text_field', default='foo') cls.cf_text.save() - cls.cf_text.obj_type.set([content_type]) + cls.cf_text.content_types.set([content_type]) # Integer custom field cls.cf_integer = CustomField(type=CustomFieldTypeChoices.TYPE_INTEGER, name='number_field', default=123) cls.cf_integer.save() - cls.cf_integer.obj_type.set([content_type]) + cls.cf_integer.content_types.set([content_type]) # Boolean custom field cls.cf_boolean = CustomField(type=CustomFieldTypeChoices.TYPE_BOOLEAN, name='boolean_field', default=False) cls.cf_boolean.save() - cls.cf_boolean.obj_type.set([content_type]) + cls.cf_boolean.content_types.set([content_type]) # Date custom field cls.cf_date = CustomField(type=CustomFieldTypeChoices.TYPE_DATE, name='date_field', default='2020-01-01') cls.cf_date.save() - cls.cf_date.obj_type.set([content_type]) + cls.cf_date.content_types.set([content_type]) # URL custom field cls.cf_url = CustomField(type=CustomFieldTypeChoices.TYPE_URL, name='url_field', default='http://example.com/1') cls.cf_url.save() - cls.cf_url.obj_type.set([content_type]) + cls.cf_url.content_types.set([content_type]) # Select custom field cls.cf_select = CustomField(type=CustomFieldTypeChoices.TYPE_SELECT, name='choice_field', choices=['Foo', 'Bar', 'Baz']) cls.cf_select.default = 'Foo' cls.cf_select.save() - cls.cf_select.obj_type.set([content_type]) + cls.cf_select.content_types.set([content_type]) # Create some sites cls.sites = ( @@ -429,7 +429,7 @@ class CustomFieldImportTest(TestCase): ) for cf in custom_fields: cf.save() - cf.obj_type.set([ContentType.objects.get_for_model(Site)]) + cf.content_types.set([ContentType.objects.get_for_model(Site)]) def test_import(self): """ diff --git a/netbox/utilities/tests/test_api.py b/netbox/utilities/tests/test_api.py index 01d4ab8f3..2cc9accaa 100644 --- a/netbox/utilities/tests/test_api.py +++ b/netbox/utilities/tests/test_api.py @@ -131,7 +131,7 @@ class APIDocsTestCase(TestCase): content_type = ContentType.objects.get_for_model(Site) self.cf_text = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='test') self.cf_text.save() - self.cf_text.obj_type.set([content_type]) + self.cf_text.content_types.set([content_type]) self.cf_text.save() def test_api_docs(self):