Rename CustomField.content_types to object_types & use ObjectType proxy

This commit is contained in:
Jeremy Stretch
2024-03-01 14:36:35 -05:00
parent 0df68bf291
commit aeeec284a5
27 changed files with 177 additions and 142 deletions

View File

@@ -7,10 +7,10 @@ from django.utils.timezone import make_aware
from rest_framework import status
from core.choices import ManagedFileRootPathChoices
from core.models import ObjectType
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Rack, Location, RackRole, Site
from extras.choices import *
from extras.models import *
from extras.reports import Report
from extras.scripts import BooleanVar, IntegerVar, Script as PythonClass, StringVar
from utilities.testing import APITestCase, APIViewTestCases
@@ -152,17 +152,17 @@ class CustomFieldTest(APIViewTestCases.APIViewTestCase):
brief_fields = ['description', 'display', 'id', 'name', 'url']
create_data = [
{
'content_types': ['dcim.site'],
'object_types': ['dcim.site'],
'name': 'cf4',
'type': 'date',
},
{
'content_types': ['dcim.site'],
'object_types': ['dcim.site'],
'name': 'cf5',
'type': 'url',
},
{
'content_types': ['dcim.site'],
'object_types': ['dcim.site'],
'name': 'cf6',
'type': 'text',
},
@@ -171,14 +171,14 @@ class CustomFieldTest(APIViewTestCases.APIViewTestCase):
'description': 'New description',
}
update_data = {
'content_types': ['dcim.device'],
'object_types': ['dcim.device'],
'name': 'New_Name',
'description': 'New description',
}
@classmethod
def setUpTestData(cls):
site_ct = ContentType.objects.get_for_model(Site)
site_ct = ObjectType.objects.get_for_model(Site)
custom_fields = (
CustomField(
@@ -196,7 +196,7 @@ class CustomFieldTest(APIViewTestCases.APIViewTestCase):
)
CustomField.objects.bulk_create(custom_fields)
for cf in custom_fields:
cf.content_types.add(site_ct)
cf.object_types.add(site_ct)
class CustomFieldChoiceSetTest(APIViewTestCases.APIViewTestCase):

View File

@@ -3,6 +3,7 @@ from django.test import override_settings
from django.urls import reverse
from rest_framework import status
from core.models import ObjectType
from dcim.choices import SiteStatusChoices
from dcim.models import Site
from extras.choices import *
@@ -23,14 +24,14 @@ class ChangeLogViewTest(ModelViewTestCase):
)
# Create a custom field on the Site model
ct = ContentType.objects.get_for_model(Site)
site_type = ObjectType.objects.get_for_model(Site)
cf = CustomField(
type=CustomFieldTypeChoices.TYPE_TEXT,
name='cf1',
required=False
)
cf.save()
cf.content_types.set([ct])
cf.object_types.set([site_type])
# Create a select custom field on the Site model
cf_select = CustomField(
@@ -40,7 +41,7 @@ class ChangeLogViewTest(ModelViewTestCase):
choice_set=choice_set
)
cf_select.save()
cf_select.content_types.set([ct])
cf_select.object_types.set([site_type])
def test_create_object(self):
tags = create_tags('Tag 1', 'Tag 2')
@@ -275,14 +276,14 @@ class ChangeLogAPITest(APITestCase):
def setUpTestData(cls):
# Create a custom field on the Site model
ct = ContentType.objects.get_for_model(Site)
site_type = ObjectType.objects.get_for_model(Site)
cf = CustomField(
type=CustomFieldTypeChoices.TYPE_TEXT,
name='cf1',
required=False
)
cf.save()
cf.content_types.set([ct])
cf.object_types.set([site_type])
# Create a select custom field on the Site model
choice_set = CustomFieldChoiceSet.objects.create(
@@ -296,7 +297,7 @@ class ChangeLogAPITest(APITestCase):
choice_set=choice_set
)
cf_select.save()
cf_select.content_types.set([ct])
cf_select.object_types.set([site_type])
# Create some tags
tags = (

View File

@@ -1,11 +1,11 @@
import datetime
from decimal import Decimal
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.urls import reverse
from rest_framework import status
from core.models import ObjectType
from dcim.filtersets import SiteFilterSet
from dcim.forms import SiteImportForm
from dcim.models import Manufacturer, Rack, Site
@@ -28,7 +28,7 @@ class CustomFieldTest(TestCase):
Site(name='Site C', slug='site-c'),
])
cls.object_type = ContentType.objects.get_for_model(Site)
cls.object_type = ObjectType.objects.get_for_model(Site)
def test_invalid_name(self):
"""
@@ -50,7 +50,7 @@ class CustomFieldTest(TestCase):
type=CustomFieldTypeChoices.TYPE_TEXT,
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -75,7 +75,7 @@ class CustomFieldTest(TestCase):
type=CustomFieldTypeChoices.TYPE_LONGTEXT,
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -99,7 +99,7 @@ class CustomFieldTest(TestCase):
type=CustomFieldTypeChoices.TYPE_INTEGER,
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -125,7 +125,7 @@ class CustomFieldTest(TestCase):
type=CustomFieldTypeChoices.TYPE_DECIMAL,
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -151,7 +151,7 @@ class CustomFieldTest(TestCase):
type=CustomFieldTypeChoices.TYPE_INTEGER,
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -178,7 +178,7 @@ class CustomFieldTest(TestCase):
type=CustomFieldTypeChoices.TYPE_DATE,
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -203,7 +203,7 @@ class CustomFieldTest(TestCase):
type=CustomFieldTypeChoices.TYPE_DATETIME,
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -228,7 +228,7 @@ class CustomFieldTest(TestCase):
type=CustomFieldTypeChoices.TYPE_URL,
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -253,7 +253,7 @@ class CustomFieldTest(TestCase):
type=CustomFieldTypeChoices.TYPE_JSON,
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -290,7 +290,7 @@ class CustomFieldTest(TestCase):
required=False,
choice_set=choice_set
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -327,7 +327,7 @@ class CustomFieldTest(TestCase):
required=False,
choice_set=choice_set
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -350,10 +350,10 @@ class CustomFieldTest(TestCase):
cf = CustomField.objects.create(
name='object_field',
type=CustomFieldTypeChoices.TYPE_OBJECT,
object_type=ContentType.objects.get_for_model(VLAN),
object_type=ObjectType.objects.get_for_model(VLAN),
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -382,10 +382,10 @@ class CustomFieldTest(TestCase):
cf = CustomField.objects.create(
name='object_field',
type=CustomFieldTypeChoices.TYPE_MULTIOBJECT,
object_type=ContentType.objects.get_for_model(VLAN),
object_type=ObjectType.objects.get_for_model(VLAN),
required=False
)
cf.content_types.set([self.object_type])
cf.object_types.set([self.object_type])
instance = Site.objects.first()
self.assertIsNone(instance.custom_field_data[cf.name])
@@ -402,13 +402,13 @@ class CustomFieldTest(TestCase):
self.assertIsNone(instance.custom_field_data.get(cf.name))
def test_rename_customfield(self):
obj_type = ContentType.objects.get_for_model(Site)
obj_type = ObjectType.objects.get_for_model(Site)
FIELD_DATA = 'abc'
# Create a custom field
cf = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='field1')
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([obj_type])
# Assign custom field data to an object
site = Site.objects.create(
@@ -437,7 +437,7 @@ class CustomFieldTest(TestCase):
)
)
site = Site.objects.create(name='Site 1', slug='site-1')
object_type = ContentType.objects.get_for_model(Site)
object_type = ObjectType.objects.get_for_model(Site)
# Text
CustomField(name='test', type='text', required=True, default="Default text").full_clean()
@@ -524,10 +524,10 @@ class CustomFieldManagerTest(TestCase):
@classmethod
def setUpTestData(cls):
content_type = ContentType.objects.get_for_model(Site)
object_type = ObjectType.objects.get_for_model(Site)
custom_field = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='text_field', default='foo')
custom_field.save()
custom_field.content_types.set([content_type])
custom_field.object_types.set([object_type])
def test_get_for_model(self):
self.assertEqual(CustomField.objects.get_for_model(Site).count(), 1)
@@ -538,7 +538,7 @@ class CustomFieldAPITest(APITestCase):
@classmethod
def setUpTestData(cls):
content_type = ContentType.objects.get_for_model(Site)
object_type = ObjectType.objects.get_for_model(Site)
# Create some VLANs
vlans = (
@@ -581,19 +581,19 @@ class CustomFieldAPITest(APITestCase):
CustomField(
type=CustomFieldTypeChoices.TYPE_OBJECT,
name='object_field',
object_type=ContentType.objects.get_for_model(VLAN),
object_type=ObjectType.objects.get_for_model(VLAN),
default=vlans[0].pk,
),
CustomField(
type=CustomFieldTypeChoices.TYPE_MULTIOBJECT,
name='multiobject_field',
object_type=ContentType.objects.get_for_model(VLAN),
object_type=ObjectType.objects.get_for_model(VLAN),
default=[vlans[0].pk, vlans[1].pk],
),
)
for cf in custom_fields:
cf.save()
cf.content_types.set([content_type])
cf.object_types.set([object_type])
# Create some sites *after* creating the custom fields. This ensures that
# default values are not set for the assigned objects.
@@ -1163,7 +1163,7 @@ class CustomFieldImportTest(TestCase):
)
for cf in custom_fields:
cf.save()
cf.content_types.set([ContentType.objects.get_for_model(Site)])
cf.object_types.set([ObjectType.objects.get_for_model(Site)])
def test_import(self):
"""
@@ -1256,11 +1256,11 @@ class CustomFieldModelTest(TestCase):
def setUpTestData(cls):
cf1 = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='foo')
cf1.save()
cf1.content_types.set([ContentType.objects.get_for_model(Site)])
cf1.object_types.set([ObjectType.objects.get_for_model(Site)])
cf2 = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='bar')
cf2.save()
cf2.content_types.set([ContentType.objects.get_for_model(Rack)])
cf2.object_types.set([ObjectType.objects.get_for_model(Rack)])
def test_cf_data(self):
"""
@@ -1299,7 +1299,7 @@ class CustomFieldModelTest(TestCase):
"""
cf3 = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='baz', required=True)
cf3.save()
cf3.content_types.set([ContentType.objects.get_for_model(Site)])
cf3.object_types.set([ObjectType.objects.get_for_model(Site)])
site = Site(name='Test Site', slug='test-site')
@@ -1318,7 +1318,7 @@ class CustomFieldModelFilterTest(TestCase):
@classmethod
def setUpTestData(cls):
obj_type = ContentType.objects.get_for_model(Site)
object_type = ObjectType.objects.get_for_model(Site)
manufacturers = Manufacturer.objects.bulk_create((
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
@@ -1335,17 +1335,17 @@ class CustomFieldModelFilterTest(TestCase):
# Integer filtering
cf = CustomField(name='cf1', type=CustomFieldTypeChoices.TYPE_INTEGER)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Decimal filtering
cf = CustomField(name='cf2', type=CustomFieldTypeChoices.TYPE_DECIMAL)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Boolean filtering
cf = CustomField(name='cf3', type=CustomFieldTypeChoices.TYPE_BOOLEAN)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Exact text filtering
cf = CustomField(
@@ -1354,7 +1354,7 @@ class CustomFieldModelFilterTest(TestCase):
filter_logic=CustomFieldFilterLogicChoices.FILTER_EXACT
)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Loose text filtering
cf = CustomField(
@@ -1363,12 +1363,12 @@ class CustomFieldModelFilterTest(TestCase):
filter_logic=CustomFieldFilterLogicChoices.FILTER_LOOSE
)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Date filtering
cf = CustomField(name='cf6', type=CustomFieldTypeChoices.TYPE_DATE)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Exact URL filtering
cf = CustomField(
@@ -1377,7 +1377,7 @@ class CustomFieldModelFilterTest(TestCase):
filter_logic=CustomFieldFilterLogicChoices.FILTER_EXACT
)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Loose URL filtering
cf = CustomField(
@@ -1386,7 +1386,7 @@ class CustomFieldModelFilterTest(TestCase):
filter_logic=CustomFieldFilterLogicChoices.FILTER_LOOSE
)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Selection filtering
cf = CustomField(
@@ -1395,7 +1395,7 @@ class CustomFieldModelFilterTest(TestCase):
choice_set=choice_set
)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Multiselect filtering
cf = CustomField(
@@ -1404,25 +1404,25 @@ class CustomFieldModelFilterTest(TestCase):
choice_set=choice_set
)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Object filtering
cf = CustomField(
name='cf11',
type=CustomFieldTypeChoices.TYPE_OBJECT,
object_type=ContentType.objects.get_for_model(Manufacturer)
object_type=ObjectType.objects.get_for_model(Manufacturer)
)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
# Multi-object filtering
cf = CustomField(
name='cf12',
type=CustomFieldTypeChoices.TYPE_MULTIOBJECT,
object_type=ContentType.objects.get_for_model(Manufacturer)
object_type=ObjectType.objects.get_for_model(Manufacturer)
)
cf.save()
cf.content_types.set([obj_type])
cf.object_types.set([object_type])
Site.objects.bulk_create([
Site(name='Site 1', slug='site-1', custom_field_data={

View File

@@ -7,6 +7,7 @@ from django.test import TestCase
from circuits.models import Provider
from core.choices import ManagedFileRootPathChoices
from core.models import ObjectType
from dcim.filtersets import SiteFilterSet
from dcim.models import DeviceRole, DeviceType, Manufacturer, Platform, Rack, Region, Site, SiteGroup
from dcim.models import Location
@@ -87,11 +88,11 @@ class CustomFieldTestCase(TestCase, BaseFilterSetTests):
),
)
CustomField.objects.bulk_create(custom_fields)
custom_fields[0].content_types.add(ContentType.objects.get_by_natural_key('dcim', 'site'))
custom_fields[1].content_types.add(ContentType.objects.get_by_natural_key('dcim', 'rack'))
custom_fields[2].content_types.add(ContentType.objects.get_by_natural_key('dcim', 'device'))
custom_fields[3].content_types.add(ContentType.objects.get_by_natural_key('dcim', 'device'))
custom_fields[4].content_types.add(ContentType.objects.get_by_natural_key('dcim', 'device'))
custom_fields[0].object_types.add(ObjectType.objects.get_by_natural_key('dcim', 'site'))
custom_fields[1].object_types.add(ObjectType.objects.get_by_natural_key('dcim', 'rack'))
custom_fields[2].object_types.add(ObjectType.objects.get_by_natural_key('dcim', 'device'))
custom_fields[3].object_types.add(ObjectType.objects.get_by_natural_key('dcim', 'device'))
custom_fields[4].object_types.add(ObjectType.objects.get_by_natural_key('dcim', 'device'))
def test_q(self):
params = {'q': 'foobar1'}
@@ -101,10 +102,10 @@ class CustomFieldTestCase(TestCase, BaseFilterSetTests):
params = {'name': ['Custom Field 1', 'Custom Field 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_by_natural_key('dcim', 'site').pk]}
params = {'object_types_id': [ObjectType.objects.get_by_natural_key('dcim', 'site').pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
def test_required(self):

View File

@@ -1,6 +1,7 @@
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from core.models import ObjectType
from dcim.forms import SiteForm
from dcim.models import Site
from extras.choices import CustomFieldTypeChoices
@@ -12,66 +13,66 @@ class CustomFieldModelFormTest(TestCase):
@classmethod
def setUpTestData(cls):
obj_type = ContentType.objects.get_for_model(Site)
object_type = ObjectType.objects.get_for_model(Site)
choice_set = CustomFieldChoiceSet.objects.create(
name='Choice Set 1',
extra_choices=(('a', 'A'), ('b', 'B'), ('c', 'C'))
)
cf_text = CustomField.objects.create(name='text', type=CustomFieldTypeChoices.TYPE_TEXT)
cf_text.content_types.set([obj_type])
cf_text.object_types.set([object_type])
cf_longtext = CustomField.objects.create(name='longtext', type=CustomFieldTypeChoices.TYPE_LONGTEXT)
cf_longtext.content_types.set([obj_type])
cf_longtext.object_types.set([object_type])
cf_integer = CustomField.objects.create(name='integer', type=CustomFieldTypeChoices.TYPE_INTEGER)
cf_integer.content_types.set([obj_type])
cf_integer.object_types.set([object_type])
cf_integer = CustomField.objects.create(name='decimal', type=CustomFieldTypeChoices.TYPE_DECIMAL)
cf_integer.content_types.set([obj_type])
cf_integer.object_types.set([object_type])
cf_boolean = CustomField.objects.create(name='boolean', type=CustomFieldTypeChoices.TYPE_BOOLEAN)
cf_boolean.content_types.set([obj_type])
cf_boolean.object_types.set([object_type])
cf_date = CustomField.objects.create(name='date', type=CustomFieldTypeChoices.TYPE_DATE)
cf_date.content_types.set([obj_type])
cf_date.object_types.set([object_type])
cf_datetime = CustomField.objects.create(name='datetime', type=CustomFieldTypeChoices.TYPE_DATETIME)
cf_datetime.content_types.set([obj_type])
cf_datetime.object_types.set([object_type])
cf_url = CustomField.objects.create(name='url', type=CustomFieldTypeChoices.TYPE_URL)
cf_url.content_types.set([obj_type])
cf_url.object_types.set([object_type])
cf_json = CustomField.objects.create(name='json', type=CustomFieldTypeChoices.TYPE_JSON)
cf_json.content_types.set([obj_type])
cf_json.object_types.set([object_type])
cf_select = CustomField.objects.create(
name='select',
type=CustomFieldTypeChoices.TYPE_SELECT,
choice_set=choice_set
)
cf_select.content_types.set([obj_type])
cf_select.object_types.set([object_type])
cf_multiselect = CustomField.objects.create(
name='multiselect',
type=CustomFieldTypeChoices.TYPE_MULTISELECT,
choice_set=choice_set
)
cf_multiselect.content_types.set([obj_type])
cf_multiselect.object_types.set([object_type])
cf_object = CustomField.objects.create(
name='object',
type=CustomFieldTypeChoices.TYPE_OBJECT,
object_type=ContentType.objects.get_for_model(Site)
)
cf_object.content_types.set([obj_type])
cf_object.object_types.set([object_type])
cf_multiobject = CustomField.objects.create(
name='multiobject',
type=CustomFieldTypeChoices.TYPE_MULTIOBJECT,
object_type=ContentType.objects.get_for_model(Site)
)
cf_multiobject.content_types.set([obj_type])
cf_multiobject.object_types.set([object_type])
def test_empty_values(self):
"""

View File

@@ -5,6 +5,7 @@ from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from core.models import ObjectType
from dcim.models import DeviceType, Manufacturer, Site
from extras.choices import *
from extras.models import *
@@ -19,7 +20,7 @@ class CustomFieldTestCase(ViewTestCases.PrimaryObjectViewTestCase):
@classmethod
def setUpTestData(cls):
site_ct = ContentType.objects.get_for_model(Site)
site_type = ObjectType.objects.get_for_model(Site)
CustomFieldChoiceSet.objects.create(
name='Choice Set 1',
extra_choices=(
@@ -36,13 +37,13 @@ class CustomFieldTestCase(ViewTestCases.PrimaryObjectViewTestCase):
)
for customfield in custom_fields:
customfield.save()
customfield.content_types.add(site_ct)
customfield.object_types.add(site_type)
cls.form_data = {
'name': 'field_x',
'label': 'Field X',
'type': 'text',
'content_types': [site_ct.pk],
'object_types': [site_type.pk],
'search_weight': 2000,
'filter_logic': CustomFieldFilterLogicChoices.FILTER_EXACT,
'default': None,
@@ -53,7 +54,7 @@ class CustomFieldTestCase(ViewTestCases.PrimaryObjectViewTestCase):
}
cls.csv_data = (
'name,label,type,content_types,object_type,weight,search_weight,filter_logic,choice_set,validation_minimum,validation_maximum,validation_regex,ui_visible,ui_editable',
'name,label,type,object_types,object_type,weight,search_weight,filter_logic,choice_set,validation_minimum,validation_maximum,validation_regex,ui_visible,ui_editable',
'field4,Field 4,text,dcim.site,,100,1000,exact,,,,[a-z]{3},always,yes',
'field5,Field 5,integer,dcim.site,,100,2000,exact,,1,100,,always,yes',
'field6,Field 6,select,dcim.site,,100,3000,exact,Choice Set 1,,,,always,yes',