def setUp(self): 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.content_types.set([content_type])
def test_select_field(self): obj_type = ContentType.objects.get_for_model(Site) # Create a custom field cf = CustomField(type=CF_TYPE_SELECT, name='my_field', required=False) cf.save() cf.obj_type = [obj_type] cf.save() # Create some choices for the field CustomFieldChoice.objects.bulk_create([ CustomFieldChoice(field=cf, value='Option A'), CustomFieldChoice(field=cf, value='Option B'), CustomFieldChoice(field=cf, value='Option C'), ]) # Assign a value to the first Site site = Site.objects.first() cfv = CustomFieldValue(field=cf, obj_type=obj_type, obj_id=site.id) cfv.value = cf.choices.first() cfv.save() # Retrieve the stored value cfv = CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).first() self.assertEqual(str(cfv.value), 'Option A') # Delete the stored value cfv.value = None cfv.save() self.assertEqual(CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).count(), 0) # Delete the custom field cf.delete()
def test_rename_customfield(self): obj_type = ContentType.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]) # Assign custom field data to an object site = Site.objects.create( name='Site 1', slug='site-1', custom_field_data={'field1': FIELD_DATA} ) site.refresh_from_db() self.assertEqual(site.custom_field_data['field1'], FIELD_DATA) # Rename the custom field cf.name = 'field2' cf.save() # Check that custom field data on the object has been updated site.refresh_from_db() self.assertNotIn('field1', site.custom_field_data) self.assertEqual(site.custom_field_data['field2'], FIELD_DATA)
def test_select_field(self): obj_type = ContentType.objects.get_for_model(Site) # Create a custom field cf = CustomField(type=CustomFieldTypeChoices.TYPE_SELECT, name='my_field', required=False) cf.save() cf.obj_type.set([obj_type]) cf.save() # Create some choices for the field CustomFieldChoice.objects.bulk_create([ CustomFieldChoice(field=cf, value='Option A'), CustomFieldChoice(field=cf, value='Option B'), CustomFieldChoice(field=cf, value='Option C'), ]) # Assign a value to the first Site site = Site.objects.first() cfv = CustomFieldValue(field=cf, obj_type=obj_type, obj_id=site.id) cfv.value = cf.choices.first() cfv.save() # Retrieve the stored value cfv = CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).first() self.assertEqual(str(cfv.value), 'Option A') # Delete the stored value cfv.value = None cfv.save() self.assertEqual(CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).count(), 0) # Delete the custom field cf.delete()
def test_select_field(self): obj_type = ContentType.objects.get_for_model(Site) # Create a custom field cf = CustomField( type=CustomFieldTypeChoices.TYPE_SELECT, name='my_field', required=False, choices=['Option A', 'Option B', 'Option C'] ) cf.save() cf.content_types.set([obj_type]) # Assign a value to the first Site site = Site.objects.first() site.custom_field_data[cf.name] = 'Option A' site.save() # Retrieve the stored value site.refresh_from_db() self.assertEqual(site.custom_field_data[cf.name], 'Option A') # Delete the stored value site.custom_field_data.pop(cf.name) site.save() site.refresh_from_db() self.assertIsNone(site.custom_field_data.get(cf.name)) # Delete the custom field cf.delete()
def setUp(self): super().setUp() # Create a custom field on the Site model ct = ContentType.objects.get_for_model(Site) cf = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='my_field', required=False) cf.save() cf.content_types.set([ct]) # Create a select custom field on the Site model cf_select = CustomField(type=CustomFieldTypeChoices.TYPE_SELECT, name='my_field_select', required=False, choices=['Bar', 'Foo']) cf_select.save() cf_select.content_types.set([ct]) # Create some tags tags = ( Tag(name='Tag 1', slug='tag-1'), Tag(name='Tag 2', slug='tag-2'), Tag(name='Tag 3', slug='tag-3'), ) Tag.objects.bulk_create(tags)
def setUpTestData(cls): cf1 = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='foo') cf1.save() cf1.content_types.set([ContentType.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)])
def setUp(self): super().setUp() # Create a custom field on the Site model ct = ContentType.objects.get_for_model(Site) cf = CustomField(type=CF_TYPE_TEXT, name='my_field', required=False) cf.save() cf.obj_type.set([ct])
def setUpTestData(cls): # Create a custom field on the Site model ct = ContentType.objects.get_for_model(Site) cf = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='my_field', required=False) cf.save() cf.obj_type.set([ct])
def setUpTestData(cls): # Create a custom field on the Site model ct = ContentType.objects.get_for_model(Site) cf = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='my_field', required=False) cf.save() cf.content_types.set([ct]) # Create a select custom field on the Site model cf_select = CustomField(type=CustomFieldTypeChoices.TYPE_SELECT, name='my_field_select', required=False, choices=['Bar', 'Foo']) cf_select.save() cf_select.content_types.set([ct])
def test_missing_required_field(self): """ Check that a ValidationError is raised if any required custom fields are not present. """ cf3 = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='baz', required=True) cf3.save() cf3.content_types.set([ContentType.objects.get_for_model(Site)]) site = Site(name='Test Site', slug='test-site') # Set custom field data with a required field omitted site.cf['foo'] = 'abc' with self.assertRaises(ValidationError): site.clean() site.cf['baz'] = 'def' site.clean()
def test_simple_fields(self): DATA = ( {'field_type': CF_TYPE_TEXT, 'field_value': 'Foobar!', 'empty_value': ''}, {'field_type': CF_TYPE_INTEGER, 'field_value': 0, 'empty_value': None}, {'field_type': CF_TYPE_INTEGER, 'field_value': 42, 'empty_value': None}, {'field_type': CF_TYPE_BOOLEAN, 'field_value': True, 'empty_value': None}, {'field_type': CF_TYPE_BOOLEAN, 'field_value': False, 'empty_value': None}, {'field_type': CF_TYPE_DATE, 'field_value': date( 2016, 6, 23), 'empty_value': None}, {'field_type': CF_TYPE_URL, 'field_value': 'http://example.com/', 'empty_value': ''}, ) obj_type = ContentType.objects.get_for_model(Site) for data in DATA: # Create a custom field cf = CustomField(type=data['field_type'], name='my_field', required=False) cf.save() cf.obj_type = [obj_type] cf.save() # Assign a value to the first Site site = Site.objects.first() cfv = CustomFieldValue(field=cf, obj_type=obj_type, obj_id=site.id) cfv.value = data['field_value'] cfv.save() # Retrieve the stored value cfv = CustomFieldValue.objects.filter( obj_type=obj_type, obj_id=site.pk).first() self.assertEqual(cfv.value, data['field_value']) # Delete the stored value cfv.value = data['empty_value'] cfv.save() self.assertEqual(CustomFieldValue.objects.filter( obj_type=obj_type, obj_id=site.pk).count(), 0) # Delete the custom field cf.delete()
class APIDocsTestCase(TestCase): def setUp(self): self.client = Client() # Populate a CustomField to activate CustomFieldSerializer 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.content_types.set([content_type]) self.cf_text.save() def test_api_docs(self): url = reverse('api_docs') params = { "format": "openapi", } response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params))) self.assertEqual(response.status_code, 200)
def test_simple_fields(self): DATA = ( {'field_type': CustomFieldTypeChoices.TYPE_TEXT, 'field_value': 'Foobar!', 'empty_value': ''}, {'field_type': CustomFieldTypeChoices.TYPE_INTEGER, 'field_value': 0, 'empty_value': None}, {'field_type': CustomFieldTypeChoices.TYPE_INTEGER, 'field_value': 42, 'empty_value': None}, {'field_type': CustomFieldTypeChoices.TYPE_BOOLEAN, 'field_value': True, 'empty_value': None}, {'field_type': CustomFieldTypeChoices.TYPE_BOOLEAN, 'field_value': False, 'empty_value': None}, {'field_type': CustomFieldTypeChoices.TYPE_DATE, 'field_value': '2016-06-23', 'empty_value': None}, {'field_type': CustomFieldTypeChoices.TYPE_URL, 'field_value': 'http://example.com/', 'empty_value': ''}, ) obj_type = ContentType.objects.get_for_model(Site) for data in DATA: # Create a custom field cf = CustomField(type=data['field_type'], name='my_field', required=False) cf.save() cf.content_types.set([obj_type]) # Check that the field has a null initial value site = Site.objects.first() self.assertIsNone(site.custom_field_data[cf.name]) # Assign a value to the first Site site.custom_field_data[cf.name] = data['field_value'] site.save() # Retrieve the stored value site.refresh_from_db() self.assertEqual(site.custom_field_data[cf.name], data['field_value']) # Delete the stored value site.custom_field_data.pop(cf.name) site.save() site.refresh_from_db() self.assertIsNone(site.custom_field_data.get(cf.name)) # Delete the custom field cf.delete()
def test_simple_fields(self): DATA = ( {'field_type': CF_TYPE_TEXT, 'field_value': 'Foobar!', 'empty_value': ''}, {'field_type': CF_TYPE_INTEGER, 'field_value': 0, 'empty_value': None}, {'field_type': CF_TYPE_INTEGER, 'field_value': 42, 'empty_value': None}, {'field_type': CF_TYPE_BOOLEAN, 'field_value': True, 'empty_value': None}, {'field_type': CF_TYPE_BOOLEAN, 'field_value': False, 'empty_value': None}, {'field_type': CF_TYPE_DATE, 'field_value': date(2016, 6, 23), 'empty_value': None}, {'field_type': CF_TYPE_URL, 'field_value': 'http://example.com/', 'empty_value': ''}, ) obj_type = ContentType.objects.get_for_model(Site) for data in DATA: # Create a custom field cf = CustomField(type=data['field_type'], name='my_field', required=False) cf.save() cf.obj_type = [obj_type] cf.save() # Assign a value to the first Site site = Site.objects.first() cfv = CustomFieldValue(field=cf, obj_type=obj_type, obj_id=site.id) cfv.value = data['field_value'] cfv.save() # Retrieve the stored value cfv = CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).first() self.assertEqual(cfv.value, data['field_value']) # Delete the stored value cfv.value = data['empty_value'] cfv.save() self.assertEqual(CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).count(), 0) # Delete the custom field cf.delete()
def handle(self, *args, **options): dry_run = options['dry_run'] quiet = options['quiet'] tenant_obj_type = ContentType.objects.get_for_model(Tenant) device_obj_type = ContentType.objects.get_for_model(Device) # Create a new Tenant Group called Members. try: tg = TenantGroup.objects.get(name="Members") except TenantGroup.DoesNotExist: tg = TenantGroup(name='Members') if dry_run: self.stdout.write( 'Would have created a Tenant Group called Members') else: tg.save() if not quiet: self.stdout.write('Created Tenant Group called Members') # Create a new Custom Field called MemberType # and add it to Tenant. try: member_type = CustomField.objects.get(name="member_type") except CustomField.DoesNotExist: member_type = CustomField( type=CustomFieldTypeChoices.TYPE_SELECT, name='member_type', required=False, choices=MEMBER_TYPES, ) if dry_run: self.stdout.write( 'Would have created a Custom Field called member_type') else: member_type.save() member_type.content_types.set([tenant_obj_type]) if not quiet: self.stdout.write( 'Created Custom Field called member_type') # Create a new Custom Field called crm_id # and add it to Tenant. try: crm_id = CustomField.objects.get(name="crm_id") except CustomField.DoesNotExist: crm_id = CustomField( type=CustomFieldTypeChoices.TYPE_TEXT, name='crm_id', required=False, default='', ) if dry_run: self.stdout.write( 'Would have created a Custom Field called crm_id') else: crm_id.save() crm_id.content_types.set([tenant_obj_type]) if not quiet: self.stdout.write('Created Custom Field called crm_id') # Create a new Custom Field called active # and add it to Tenant. try: active = CustomField.objects.get(name="active") except CustomField.DoesNotExist: active = CustomField( type=CustomFieldTypeChoices.TYPE_BOOLEAN, name='active', required=False, default=True, ) if dry_run: self.stdout.write( 'Would have created a Custom Field called active') else: active.save() active.content_types.set([tenant_obj_type]) if not quiet: self.stdout.write('Created Custom Field called active') # Create a new Custom Field called legacy_id # and add it to Device try: legacy_id = CustomField.objects.get(name="legacy_id") except CustomField.DoesNotExist: legacy_id = CustomField( type=CustomFieldTypeChoices.TYPE_TEXT, name='legacy_id', required=False, default='', ) if dry_run: self.stdout.write( 'Would have created a Custom Field called legacy_id') else: legacy_id.save() legacy_id.content_types.set([device_obj_type]) if not quiet: self.stdout.write('Created Custom Field called legacy_id')
def setUpTestData(cls): obj_type = ContentType.objects.get_for_model(Site) # Integer filtering cf = CustomField(name='cf1', type=CustomFieldTypeChoices.TYPE_INTEGER) cf.save() cf.content_types.set([obj_type]) # Boolean filtering cf = CustomField(name='cf2', type=CustomFieldTypeChoices.TYPE_BOOLEAN) cf.save() cf.content_types.set([obj_type]) # Exact text filtering cf = CustomField(name='cf3', type=CustomFieldTypeChoices.TYPE_TEXT, filter_logic=CustomFieldFilterLogicChoices.FILTER_EXACT) cf.save() cf.content_types.set([obj_type]) # Loose text filtering cf = CustomField(name='cf4', type=CustomFieldTypeChoices.TYPE_TEXT, filter_logic=CustomFieldFilterLogicChoices.FILTER_LOOSE) cf.save() cf.content_types.set([obj_type]) # Date filtering cf = CustomField(name='cf5', type=CustomFieldTypeChoices.TYPE_DATE) cf.save() cf.content_types.set([obj_type]) # Exact URL filtering cf = CustomField(name='cf6', type=CustomFieldTypeChoices.TYPE_URL, filter_logic=CustomFieldFilterLogicChoices.FILTER_EXACT) cf.save() cf.content_types.set([obj_type]) # Loose URL filtering cf = CustomField(name='cf7', type=CustomFieldTypeChoices.TYPE_URL, filter_logic=CustomFieldFilterLogicChoices.FILTER_LOOSE) cf.save() cf.content_types.set([obj_type]) # Selection filtering cf = CustomField(name='cf8', type=CustomFieldTypeChoices.TYPE_URL, choices=['Foo', 'Bar', 'Baz']) cf.save() cf.content_types.set([obj_type]) Site.objects.bulk_create([ Site(name='Site 1', slug='site-1', custom_field_data={ 'cf1': 100, 'cf2': True, 'cf3': 'foo', 'cf4': 'foo', 'cf5': '2016-06-26', 'cf6': 'http://foo.example.com/', 'cf7': 'http://foo.example.com/', 'cf8': 'Foo', }), Site(name='Site 2', slug='site-2', custom_field_data={ 'cf1': 200, 'cf2': False, 'cf3': 'foobar', 'cf4': 'foobar', 'cf5': '2016-06-27', 'cf6': 'http://bar.example.com/', 'cf7': 'http://bar.example.com/', 'cf8': 'Bar', }), Site(name='Site 3', slug='site-3', custom_field_data={ }), ])
class CustomFieldAPITest(HttpStatusMixin, APITestCase): def setUp(self): user = User.objects.create(username='******', is_superuser=True) token = Token.objects.create(user=user) self.header = {'HTTP_AUTHORIZATION': 'Token {}'.format(token.key)} content_type = ContentType.objects.get_for_model(Site) # Text custom field self.cf_text = CustomField(type=CF_TYPE_TEXT, name='magic_word') self.cf_text.save() self.cf_text.obj_type = [content_type] self.cf_text.save() # Integer custom field self.cf_integer = CustomField(type=CF_TYPE_INTEGER, name='magic_number') self.cf_integer.save() self.cf_integer.obj_type = [content_type] self.cf_integer.save() # Boolean custom field self.cf_boolean = CustomField(type=CF_TYPE_BOOLEAN, name='is_magic') self.cf_boolean.save() self.cf_boolean.obj_type = [content_type] self.cf_boolean.save() # Date custom field self.cf_date = CustomField(type=CF_TYPE_DATE, name='magic_date') self.cf_date.save() self.cf_date.obj_type = [content_type] self.cf_date.save() # URL custom field self.cf_url = CustomField(type=CF_TYPE_URL, name='magic_url') self.cf_url.save() self.cf_url.obj_type = [content_type] self.cf_url.save() # Select custom field self.cf_select = CustomField(type=CF_TYPE_SELECT, name='magic_choice') self.cf_select.save() self.cf_select.obj_type = [content_type] self.cf_select.save() self.cf_select_choice1 = CustomFieldChoice(field=self.cf_select, value='Foo') self.cf_select_choice1.save() self.cf_select_choice2 = CustomFieldChoice(field=self.cf_select, value='Bar') self.cf_select_choice2.save() self.cf_select_choice3 = CustomFieldChoice(field=self.cf_select, value='Baz') self.cf_select_choice3.save() self.site = Site.objects.create(name='Test Site 1', slug='test-site-1') def test_get_obj_without_custom_fields(self): url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.get(url, **self.header) self.assertEqual(response.data['name'], self.site.name) self.assertEqual(response.data['custom_fields'], { 'magic_word': None, 'magic_number': None, 'is_magic': None, 'magic_date': None, 'magic_url': None, 'magic_choice': None, }) def test_get_obj_with_custom_fields(self): CUSTOM_FIELD_VALUES = [ (self.cf_text, 'Test string'), (self.cf_integer, 1234), (self.cf_boolean, True), (self.cf_date, date(2016, 6, 23)), (self.cf_url, 'http://example.com/'), (self.cf_select, self.cf_select_choice1.pk), ] for field, value in CUSTOM_FIELD_VALUES: cfv = CustomFieldValue(field=field, obj=self.site) cfv.value = value cfv.save() url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.get(url, **self.header) self.assertEqual(response.data['name'], self.site.name) self.assertEqual(response.data['custom_fields'].get('magic_word'), CUSTOM_FIELD_VALUES[0][1]) self.assertEqual(response.data['custom_fields'].get('magic_number'), CUSTOM_FIELD_VALUES[1][1]) self.assertEqual(response.data['custom_fields'].get('is_magic'), CUSTOM_FIELD_VALUES[2][1]) self.assertEqual(response.data['custom_fields'].get('magic_date'), CUSTOM_FIELD_VALUES[3][1]) self.assertEqual(response.data['custom_fields'].get('magic_url'), CUSTOM_FIELD_VALUES[4][1]) self.assertEqual(response.data['custom_fields'].get('magic_choice'), { 'value': self.cf_select_choice1.pk, 'label': 'Foo' }) def test_set_custom_field_text(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_word': 'Foo bar baz', } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_word'), data['custom_fields']['magic_word']) cfv = self.site.custom_field_values.get(field=self.cf_text) self.assertEqual(cfv.value, data['custom_fields']['magic_word']) def test_set_custom_field_integer(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_number': 42, } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_number'), data['custom_fields']['magic_number']) cfv = self.site.custom_field_values.get(field=self.cf_integer) self.assertEqual(cfv.value, data['custom_fields']['magic_number']) def test_set_custom_field_boolean(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'is_magic': 0, } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('is_magic'), data['custom_fields']['is_magic']) cfv = self.site.custom_field_values.get(field=self.cf_boolean) self.assertEqual(cfv.value, data['custom_fields']['is_magic']) def test_set_custom_field_date(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_date': '2017-04-25', } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_date'), data['custom_fields']['magic_date']) cfv = self.site.custom_field_values.get(field=self.cf_date) self.assertEqual(cfv.value.isoformat(), data['custom_fields']['magic_date']) def test_set_custom_field_url(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_url': 'http://example.com/2/', } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_url'), data['custom_fields']['magic_url']) cfv = self.site.custom_field_values.get(field=self.cf_url) self.assertEqual(cfv.value, data['custom_fields']['magic_url']) def test_set_custom_field_select(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_choice': self.cf_select_choice2.pk, } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_choice'), data['custom_fields']['magic_choice']) cfv = self.site.custom_field_values.get(field=self.cf_select) self.assertEqual(cfv.value.pk, data['custom_fields']['magic_choice'])
def test_simple_fields(self): DATA = ( { 'field': { 'type': CustomFieldTypeChoices.TYPE_TEXT, }, 'value': 'Foobar!', }, { 'field': { 'type': CustomFieldTypeChoices.TYPE_LONGTEXT, }, 'value': 'Text with **Markdown**', }, { 'field': { 'type': CustomFieldTypeChoices.TYPE_INTEGER, }, 'value': 0, }, { 'field': { 'type': CustomFieldTypeChoices.TYPE_INTEGER, 'validation_minimum': 1, 'validation_maximum': 100, }, 'value': 42, }, { 'field': { 'type': CustomFieldTypeChoices.TYPE_INTEGER, 'validation_minimum': -100, 'validation_maximum': -1, }, 'value': -42, }, { 'field': { 'type': CustomFieldTypeChoices.TYPE_BOOLEAN, }, 'value': True, }, { 'field': { 'type': CustomFieldTypeChoices.TYPE_BOOLEAN, }, 'value': False, }, { 'field': { 'type': CustomFieldTypeChoices.TYPE_DATE, }, 'value': '2016-06-23', }, { 'field': { 'type': CustomFieldTypeChoices.TYPE_URL, }, 'value': 'http://example.com/', }, { 'field': { 'type': CustomFieldTypeChoices.TYPE_JSON, }, 'value': '{"foo": 1, "bar": 2}', }, ) obj_type = ContentType.objects.get_for_model(Site) for data in DATA: # Create a custom field cf = CustomField(name='my_field', required=False, **data['field']) cf.save() cf.content_types.set([obj_type]) # Check that the field has a null initial value site = Site.objects.first() self.assertIsNone(site.custom_field_data[cf.name]) # Assign a value to the first Site site.custom_field_data[cf.name] = data['value'] site.save() # Retrieve the stored value site.refresh_from_db() self.assertEqual(site.custom_field_data[cf.name], data['value']) # Delete the stored value site.custom_field_data.pop(cf.name) site.save() site.refresh_from_db() self.assertIsNone(site.custom_field_data.get(cf.name)) # Delete the custom field cf.delete()
class CustomFieldAPITest(APITestCase): def setUp(self): super(CustomFieldAPITest, self).setUp() content_type = ContentType.objects.get_for_model(Site) # Text custom field self.cf_text = CustomField(type=CF_TYPE_TEXT, name='magic_word') self.cf_text.save() self.cf_text.obj_type.set([content_type]) self.cf_text.save() # Integer custom field self.cf_integer = CustomField(type=CF_TYPE_INTEGER, name='magic_number') self.cf_integer.save() self.cf_integer.obj_type.set([content_type]) self.cf_integer.save() # Boolean custom field self.cf_boolean = CustomField(type=CF_TYPE_BOOLEAN, name='is_magic') self.cf_boolean.save() self.cf_boolean.obj_type.set([content_type]) self.cf_boolean.save() # Date custom field self.cf_date = CustomField(type=CF_TYPE_DATE, name='magic_date') self.cf_date.save() self.cf_date.obj_type.set([content_type]) self.cf_date.save() # URL custom field self.cf_url = CustomField(type=CF_TYPE_URL, name='magic_url') self.cf_url.save() self.cf_url.obj_type.set([content_type]) self.cf_url.save() # Select custom field self.cf_select = CustomField(type=CF_TYPE_SELECT, name='magic_choice') self.cf_select.save() self.cf_select.obj_type.set([content_type]) self.cf_select.save() self.cf_select_choice1 = CustomFieldChoice(field=self.cf_select, value='Foo') self.cf_select_choice1.save() self.cf_select_choice2 = CustomFieldChoice(field=self.cf_select, value='Bar') self.cf_select_choice2.save() self.cf_select_choice3 = CustomFieldChoice(field=self.cf_select, value='Baz') self.cf_select_choice3.save() self.site = Site.objects.create(name='Test Site 1', slug='test-site-1') def test_get_obj_without_custom_fields(self): url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.get(url, **self.header) self.assertEqual(response.data['name'], self.site.name) self.assertEqual( response.data['custom_fields'], { 'magic_word': None, 'magic_number': None, 'is_magic': None, 'magic_date': None, 'magic_url': None, 'magic_choice': None, }) def test_get_obj_with_custom_fields(self): CUSTOM_FIELD_VALUES = [ (self.cf_text, 'Test string'), (self.cf_integer, 1234), (self.cf_boolean, True), (self.cf_date, date(2016, 6, 23)), (self.cf_url, 'http://example.com/'), (self.cf_select, self.cf_select_choice1.pk), ] for field, value in CUSTOM_FIELD_VALUES: cfv = CustomFieldValue(field=field, obj=self.site) cfv.value = value cfv.save() url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.get(url, **self.header) self.assertEqual(response.data['name'], self.site.name) self.assertEqual(response.data['custom_fields'].get('magic_word'), CUSTOM_FIELD_VALUES[0][1]) self.assertEqual(response.data['custom_fields'].get('magic_number'), CUSTOM_FIELD_VALUES[1][1]) self.assertEqual(response.data['custom_fields'].get('is_magic'), CUSTOM_FIELD_VALUES[2][1]) self.assertEqual(response.data['custom_fields'].get('magic_date'), CUSTOM_FIELD_VALUES[3][1]) self.assertEqual(response.data['custom_fields'].get('magic_url'), CUSTOM_FIELD_VALUES[4][1]) self.assertEqual(response.data['custom_fields'].get('magic_choice'), { 'value': self.cf_select_choice1.pk, 'label': 'Foo' }) def test_set_custom_field_text(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_word': 'Foo bar baz', } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_word'), data['custom_fields']['magic_word']) cfv = self.site.custom_field_values.get(field=self.cf_text) self.assertEqual(cfv.value, data['custom_fields']['magic_word']) def test_set_custom_field_integer(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_number': 42, } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_number'), data['custom_fields']['magic_number']) cfv = self.site.custom_field_values.get(field=self.cf_integer) self.assertEqual(cfv.value, data['custom_fields']['magic_number']) def test_set_custom_field_boolean(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'is_magic': 0, } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('is_magic'), data['custom_fields']['is_magic']) cfv = self.site.custom_field_values.get(field=self.cf_boolean) self.assertEqual(cfv.value, data['custom_fields']['is_magic']) def test_set_custom_field_date(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_date': '2017-04-25', } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_date'), data['custom_fields']['magic_date']) cfv = self.site.custom_field_values.get(field=self.cf_date) self.assertEqual(cfv.value.isoformat(), data['custom_fields']['magic_date']) def test_set_custom_field_url(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_url': 'http://example.com/2/', } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_url'), data['custom_fields']['magic_url']) cfv = self.site.custom_field_values.get(field=self.cf_url) self.assertEqual(cfv.value, data['custom_fields']['magic_url']) def test_set_custom_field_select(self): data = { 'name': 'Test Site 1', 'slug': 'test-site-1', 'custom_fields': { 'magic_choice': self.cf_select_choice2.pk, } } url = reverse('dcim-api:site-detail', kwargs={'pk': self.site.pk}) response = self.client.put(url, data, format='json', **self.header) self.assertHttpStatus(response, status.HTTP_200_OK) self.assertEqual(response.data['custom_fields'].get('magic_choice'), data['custom_fields']['magic_choice']) cfv = self.site.custom_field_values.get(field=self.cf_select) self.assertEqual(cfv.value.pk, data['custom_fields']['magic_choice'])