mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
CustomField.type to slug
This commit is contained in:
@ -5,7 +5,7 @@ from django.db import transaction
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
|
||||||
from extras.constants import *
|
from extras.choices import *
|
||||||
from extras.models import CustomField, CustomFieldChoice, CustomFieldValue
|
from extras.models import CustomField, CustomFieldChoice, CustomFieldValue
|
||||||
from utilities.api import ValidatedModelSerializer
|
from utilities.api import ValidatedModelSerializer
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ class CustomFieldsSerializer(serializers.BaseSerializer):
|
|||||||
if value not in [None, '']:
|
if value not in [None, '']:
|
||||||
|
|
||||||
# Validate integer
|
# Validate integer
|
||||||
if cf.type == CF_TYPE_INTEGER:
|
if cf.type == CustomFieldTypeChoices.TYPE_INTEGER:
|
||||||
try:
|
try:
|
||||||
int(value)
|
int(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -46,13 +46,13 @@ class CustomFieldsSerializer(serializers.BaseSerializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Validate boolean
|
# Validate boolean
|
||||||
if cf.type == CF_TYPE_BOOLEAN and value not in [True, False, 1, 0]:
|
if cf.type == CustomFieldTypeChoices.TYPE_BOOLEAN and value not in [True, False, 1, 0]:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
"Invalid value for boolean field {}: {}".format(field_name, value)
|
"Invalid value for boolean field {}: {}".format(field_name, value)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Validate date
|
# Validate date
|
||||||
if cf.type == CF_TYPE_DATE:
|
if cf.type == CustomFieldTypeChoices.TYPE_DATE:
|
||||||
try:
|
try:
|
||||||
datetime.strptime(value, '%Y-%m-%d')
|
datetime.strptime(value, '%Y-%m-%d')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -61,7 +61,7 @@ class CustomFieldsSerializer(serializers.BaseSerializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Validate selected choice
|
# Validate selected choice
|
||||||
if cf.type == CF_TYPE_SELECT:
|
if cf.type == CustomFieldTypeChoices.TYPE_SELECT:
|
||||||
try:
|
try:
|
||||||
value = int(value)
|
value = int(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -100,7 +100,7 @@ class CustomFieldModelSerializer(ValidatedModelSerializer):
|
|||||||
instance.custom_fields = {}
|
instance.custom_fields = {}
|
||||||
for field in fields:
|
for field in fields:
|
||||||
value = instance.cf.get(field.name)
|
value = instance.cf.get(field.name)
|
||||||
if field.type == CF_TYPE_SELECT and value is not None:
|
if field.type == CustomFieldTypeChoices.TYPE_SELECT and value is not None:
|
||||||
instance.custom_fields[field.name] = CustomFieldChoiceSerializer(value).data
|
instance.custom_fields[field.name] = CustomFieldChoiceSerializer(value).data
|
||||||
else:
|
else:
|
||||||
instance.custom_fields[field.name] = value
|
instance.custom_fields[field.name] = value
|
||||||
|
33
netbox/extras/choices.py
Normal file
33
netbox/extras/choices.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from utilities.choices import ChoiceSet
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# CustomFields
|
||||||
|
#
|
||||||
|
|
||||||
|
class CustomFieldTypeChoices(ChoiceSet):
|
||||||
|
|
||||||
|
TYPE_TEXT = 'text'
|
||||||
|
TYPE_INTEGER = 'integer'
|
||||||
|
TYPE_BOOLEAN = 'boolean'
|
||||||
|
TYPE_DATE = 'date'
|
||||||
|
TYPE_URL = 'url'
|
||||||
|
TYPE_SELECT = 'select'
|
||||||
|
|
||||||
|
CHOICES = (
|
||||||
|
(TYPE_TEXT, 'Text'),
|
||||||
|
(TYPE_INTEGER, 'Integer'),
|
||||||
|
(TYPE_BOOLEAN, 'Boolean (true/false)'),
|
||||||
|
(TYPE_DATE, 'Date'),
|
||||||
|
(TYPE_URL, 'URL'),
|
||||||
|
(TYPE_SELECT, 'Selection'),
|
||||||
|
)
|
||||||
|
|
||||||
|
LEGACY_MAP = {
|
||||||
|
TYPE_TEXT: 100,
|
||||||
|
TYPE_INTEGER: 200,
|
||||||
|
TYPE_BOOLEAN: 300,
|
||||||
|
TYPE_DATE: 400,
|
||||||
|
TYPE_URL: 500,
|
||||||
|
TYPE_SELECT: 600,
|
||||||
|
}
|
@ -19,22 +19,6 @@ CUSTOMFIELD_MODELS = [
|
|||||||
'virtualization.virtualmachine',
|
'virtualization.virtualmachine',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Custom field types
|
|
||||||
CF_TYPE_TEXT = 100
|
|
||||||
CF_TYPE_INTEGER = 200
|
|
||||||
CF_TYPE_BOOLEAN = 300
|
|
||||||
CF_TYPE_DATE = 400
|
|
||||||
CF_TYPE_URL = 500
|
|
||||||
CF_TYPE_SELECT = 600
|
|
||||||
CUSTOMFIELD_TYPE_CHOICES = (
|
|
||||||
(CF_TYPE_TEXT, 'Text'),
|
|
||||||
(CF_TYPE_INTEGER, 'Integer'),
|
|
||||||
(CF_TYPE_BOOLEAN, 'Boolean (true/false)'),
|
|
||||||
(CF_TYPE_DATE, 'Date'),
|
|
||||||
(CF_TYPE_URL, 'URL'),
|
|
||||||
(CF_TYPE_SELECT, 'Selection'),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Custom field filter logic choices
|
# Custom field filter logic choices
|
||||||
CF_FILTER_DISABLED = 0
|
CF_FILTER_DISABLED = 0
|
||||||
CF_FILTER_LOOSE = 1
|
CF_FILTER_LOOSE = 1
|
||||||
|
@ -4,6 +4,7 @@ from django.db.models import Q
|
|||||||
|
|
||||||
from dcim.models import DeviceRole, Platform, Region, Site
|
from dcim.models import DeviceRole, Platform, Region, Site
|
||||||
from tenancy.models import Tenant, TenantGroup
|
from tenancy.models import Tenant, TenantGroup
|
||||||
|
from .choices import *
|
||||||
from .constants import *
|
from .constants import *
|
||||||
from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, Tag
|
from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, Tag
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ class CustomFieldFilter(django_filters.Filter):
|
|||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
# Selection fields get special treatment (values must be integers)
|
# Selection fields get special treatment (values must be integers)
|
||||||
if self.cf_type == CF_TYPE_SELECT:
|
if self.cf_type == CustomFieldTypeChoices.TYPE_SELECT:
|
||||||
try:
|
try:
|
||||||
# Treat 0 as None
|
# Treat 0 as None
|
||||||
if int(value) == 0:
|
if int(value) == 0:
|
||||||
@ -42,7 +43,7 @@ class CustomFieldFilter(django_filters.Filter):
|
|||||||
return queryset.none()
|
return queryset.none()
|
||||||
|
|
||||||
# Apply the assigned filter logic (exact or loose)
|
# Apply the assigned filter logic (exact or loose)
|
||||||
if self.cf_type == CF_TYPE_BOOLEAN or self.filter_logic == CF_FILTER_EXACT:
|
if self.cf_type == CustomFieldTypeChoices.TYPE_BOOLEAN or self.filter_logic == CF_FILTER_EXACT:
|
||||||
queryset = queryset.filter(
|
queryset = queryset.filter(
|
||||||
custom_field_values__field__name=self.field_name,
|
custom_field_values__field__name=self.field_name,
|
||||||
custom_field_values__serialized_value=value
|
custom_field_values__serialized_value=value
|
||||||
|
@ -13,6 +13,7 @@ from utilities.forms import (
|
|||||||
CommentField, ContentTypeSelect, FilterChoiceField, LaxURLField, JSONField, SlugField, StaticSelect2,
|
CommentField, ContentTypeSelect, FilterChoiceField, LaxURLField, JSONField, SlugField, StaticSelect2,
|
||||||
BOOLEAN_WITH_BLANK_CHOICES,
|
BOOLEAN_WITH_BLANK_CHOICES,
|
||||||
)
|
)
|
||||||
|
from .choices import *
|
||||||
from .constants import *
|
from .constants import *
|
||||||
from .models import ConfigContext, CustomField, CustomFieldValue, ImageAttachment, ObjectChange, Tag
|
from .models import ConfigContext, CustomField, CustomFieldValue, ImageAttachment, ObjectChange, Tag
|
||||||
|
|
||||||
@ -35,11 +36,11 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F
|
|||||||
initial = cf.default if not bulk_edit else None
|
initial = cf.default if not bulk_edit else None
|
||||||
|
|
||||||
# Integer
|
# Integer
|
||||||
if cf.type == CF_TYPE_INTEGER:
|
if cf.type == CustomFieldTypeChoices.TYPE_INTEGER:
|
||||||
field = forms.IntegerField(required=cf.required, initial=initial)
|
field = forms.IntegerField(required=cf.required, initial=initial)
|
||||||
|
|
||||||
# Boolean
|
# Boolean
|
||||||
elif cf.type == CF_TYPE_BOOLEAN:
|
elif cf.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
|
||||||
choices = (
|
choices = (
|
||||||
(None, '---------'),
|
(None, '---------'),
|
||||||
(1, 'True'),
|
(1, 'True'),
|
||||||
@ -56,11 +57,11 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Date
|
# Date
|
||||||
elif cf.type == CF_TYPE_DATE:
|
elif cf.type == CustomFieldTypeChoices.TYPE_DATE:
|
||||||
field = forms.DateField(required=cf.required, initial=initial, help_text="Date format: YYYY-MM-DD")
|
field = forms.DateField(required=cf.required, initial=initial, help_text="Date format: YYYY-MM-DD")
|
||||||
|
|
||||||
# Select
|
# Select
|
||||||
elif cf.type == CF_TYPE_SELECT:
|
elif cf.type == CustomFieldTypeChoices.TYPE_SELECT:
|
||||||
choices = [(cfc.pk, cfc) for cfc in cf.choices.all()]
|
choices = [(cfc.pk, cfc) for cfc in cf.choices.all()]
|
||||||
if not cf.required or bulk_edit or filterable_only:
|
if not cf.required or bulk_edit or filterable_only:
|
||||||
choices = [(None, '---------')] + choices
|
choices = [(None, '---------')] + choices
|
||||||
@ -74,7 +75,7 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F
|
|||||||
field = forms.TypedChoiceField(choices=choices, coerce=int, required=cf.required, initial=default_choice)
|
field = forms.TypedChoiceField(choices=choices, coerce=int, required=cf.required, initial=default_choice)
|
||||||
|
|
||||||
# URL
|
# URL
|
||||||
elif cf.type == CF_TYPE_URL:
|
elif cf.type == CustomFieldTypeChoices.TYPE_URL:
|
||||||
field = LaxURLField(required=cf.required, initial=initial)
|
field = LaxURLField(required=cf.required, initial=initial)
|
||||||
|
|
||||||
# Text
|
# Text
|
||||||
|
@ -8,8 +8,6 @@ import django.db.models.deletion
|
|||||||
import extras.models
|
import extras.models
|
||||||
from django.db.utils import OperationalError
|
from django.db.utils import OperationalError
|
||||||
|
|
||||||
from extras.constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_FILTER_LOOSE, CF_TYPE_SELECT
|
|
||||||
|
|
||||||
|
|
||||||
def verify_postgresql_version(apps, schema_editor):
|
def verify_postgresql_version(apps, schema_editor):
|
||||||
"""
|
"""
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# Generated by Django 1.11.9 on 2018-02-21 19:48
|
# Generated by Django 1.11.9 on 2018-02-21 19:48
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
from extras.constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_FILTER_LOOSE, CF_TYPE_SELECT
|
from extras.constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_FILTER_LOOSE
|
||||||
|
|
||||||
|
|
||||||
def is_filterable_to_filter_logic(apps, schema_editor):
|
def is_filterable_to_filter_logic(apps, schema_editor):
|
||||||
@ -10,7 +10,7 @@ def is_filterable_to_filter_logic(apps, schema_editor):
|
|||||||
CustomField.objects.filter(is_filterable=False).update(filter_logic=CF_FILTER_DISABLED)
|
CustomField.objects.filter(is_filterable=False).update(filter_logic=CF_FILTER_DISABLED)
|
||||||
CustomField.objects.filter(is_filterable=True).update(filter_logic=CF_FILTER_LOOSE)
|
CustomField.objects.filter(is_filterable=True).update(filter_logic=CF_FILTER_LOOSE)
|
||||||
# Select fields match on primary key only
|
# Select fields match on primary key only
|
||||||
CustomField.objects.filter(is_filterable=True, type=CF_TYPE_SELECT).update(filter_logic=CF_FILTER_EXACT)
|
CustomField.objects.filter(is_filterable=True, type=600).update(filter_logic=CF_FILTER_EXACT)
|
||||||
|
|
||||||
|
|
||||||
def filter_logic_to_is_filterable(apps, schema_editor):
|
def filter_logic_to_is_filterable(apps, schema_editor):
|
||||||
|
36
netbox/extras/migrations/0029_3569_customfield_fields.py
Normal file
36
netbox/extras/migrations/0029_3569_customfield_fields.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
CUSTOMFIELD_TYPE_CHOICES = (
|
||||||
|
(100, 'text'),
|
||||||
|
(200, 'integer'),
|
||||||
|
(300, 'boolean'),
|
||||||
|
(400, 'date'),
|
||||||
|
(500, 'url'),
|
||||||
|
(600, 'select')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def customfield_type_to_slug(apps, schema_editor):
|
||||||
|
CustomField = apps.get_model('extras', 'CustomField')
|
||||||
|
for id, slug in CUSTOMFIELD_TYPE_CHOICES:
|
||||||
|
CustomField.objects.filter(type=str(id)).update(type=slug)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
atomic = False
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('extras', '0028_remove_topology_maps'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='customfield',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(default='text', max_length=50),
|
||||||
|
),
|
||||||
|
migrations.RunPython(
|
||||||
|
code=customfield_type_to_slug
|
||||||
|
),
|
||||||
|
]
|
@ -15,6 +15,7 @@ from taggit.models import TagBase, GenericTaggedItemBase
|
|||||||
|
|
||||||
from utilities.fields import ColorField
|
from utilities.fields import ColorField
|
||||||
from utilities.utils import deepmerge, model_names_to_filter_dict
|
from utilities.utils import deepmerge, model_names_to_filter_dict
|
||||||
|
from .choices import *
|
||||||
from .constants import *
|
from .constants import *
|
||||||
from .querysets import ConfigContextQuerySet
|
from .querysets import ConfigContextQuerySet
|
||||||
|
|
||||||
@ -182,9 +183,10 @@ class CustomField(models.Model):
|
|||||||
limit_choices_to=get_custom_field_models,
|
limit_choices_to=get_custom_field_models,
|
||||||
help_text='The object(s) to which this field applies.'
|
help_text='The object(s) to which this field applies.'
|
||||||
)
|
)
|
||||||
type = models.PositiveSmallIntegerField(
|
type = models.CharField(
|
||||||
choices=CUSTOMFIELD_TYPE_CHOICES,
|
max_length=50,
|
||||||
default=CF_TYPE_TEXT
|
choices=CustomFieldTypeChoices,
|
||||||
|
default=CustomFieldTypeChoices.TYPE_TEXT
|
||||||
)
|
)
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
max_length=50,
|
max_length=50,
|
||||||
@ -233,15 +235,15 @@ class CustomField(models.Model):
|
|||||||
"""
|
"""
|
||||||
if value is None:
|
if value is None:
|
||||||
return ''
|
return ''
|
||||||
if self.type == CF_TYPE_BOOLEAN:
|
if self.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
|
||||||
return str(int(bool(value)))
|
return str(int(bool(value)))
|
||||||
if self.type == CF_TYPE_DATE:
|
if self.type == CustomFieldTypeChoices.TYPE_DATE:
|
||||||
# Could be date/datetime object or string
|
# Could be date/datetime object or string
|
||||||
try:
|
try:
|
||||||
return value.strftime('%Y-%m-%d')
|
return value.strftime('%Y-%m-%d')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return value
|
return value
|
||||||
if self.type == CF_TYPE_SELECT:
|
if self.type == CustomFieldTypeChoices.TYPE_SELECT:
|
||||||
# Could be ModelChoiceField or TypedChoiceField
|
# Could be ModelChoiceField or TypedChoiceField
|
||||||
return str(value.id) if hasattr(value, 'id') else str(value)
|
return str(value.id) if hasattr(value, 'id') else str(value)
|
||||||
return value
|
return value
|
||||||
@ -252,14 +254,14 @@ class CustomField(models.Model):
|
|||||||
"""
|
"""
|
||||||
if serialized_value == '':
|
if serialized_value == '':
|
||||||
return None
|
return None
|
||||||
if self.type == CF_TYPE_INTEGER:
|
if self.type == CustomFieldTypeChoices.TYPE_INTEGER:
|
||||||
return int(serialized_value)
|
return int(serialized_value)
|
||||||
if self.type == CF_TYPE_BOOLEAN:
|
if self.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
|
||||||
return bool(int(serialized_value))
|
return bool(int(serialized_value))
|
||||||
if self.type == CF_TYPE_DATE:
|
if self.type == CustomFieldTypeChoices.TYPE_DATE:
|
||||||
# Read date as YYYY-MM-DD
|
# Read date as YYYY-MM-DD
|
||||||
return date(*[int(n) for n in serialized_value.split('-')])
|
return date(*[int(n) for n in serialized_value.split('-')])
|
||||||
if self.type == CF_TYPE_SELECT:
|
if self.type == CustomFieldTypeChoices.TYPE_SELECT:
|
||||||
return self.choices.get(pk=int(serialized_value))
|
return self.choices.get(pk=int(serialized_value))
|
||||||
return serialized_value
|
return serialized_value
|
||||||
|
|
||||||
@ -312,7 +314,7 @@ class CustomFieldChoice(models.Model):
|
|||||||
to='extras.CustomField',
|
to='extras.CustomField',
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='choices',
|
related_name='choices',
|
||||||
limit_choices_to={'type': CF_TYPE_SELECT}
|
limit_choices_to={'type': CustomFieldTypeChoices.TYPE_SELECT}
|
||||||
)
|
)
|
||||||
value = models.CharField(
|
value = models.CharField(
|
||||||
max_length=100
|
max_length=100
|
||||||
@ -330,14 +332,17 @@ class CustomFieldChoice(models.Model):
|
|||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.field.type != CF_TYPE_SELECT:
|
if self.field.type != CustomFieldTypeChoices.TYPE_SELECT:
|
||||||
raise ValidationError("Custom field choices can only be assigned to selection fields.")
|
raise ValidationError("Custom field choices can only be assigned to selection fields.")
|
||||||
|
|
||||||
def delete(self, using=None, keep_parents=False):
|
def delete(self, using=None, keep_parents=False):
|
||||||
# When deleting a CustomFieldChoice, delete all CustomFieldValues which point to it
|
# When deleting a CustomFieldChoice, delete all CustomFieldValues which point to it
|
||||||
pk = self.pk
|
pk = self.pk
|
||||||
super().delete(using, keep_parents)
|
super().delete(using, keep_parents)
|
||||||
CustomFieldValue.objects.filter(field__type=CF_TYPE_SELECT, serialized_value=str(pk)).delete()
|
CustomFieldValue.objects.filter(
|
||||||
|
field__type=CustomFieldTypeChoices.TYPE_SELECT,
|
||||||
|
serialized_value=str(pk)
|
||||||
|
).delete()
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -3,6 +3,7 @@ from django.urls import reverse
|
|||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
from dcim.models import Site
|
from dcim.models import Site
|
||||||
|
from extras.choices import *
|
||||||
from extras.constants import *
|
from extras.constants import *
|
||||||
from extras.models import CustomField, CustomFieldValue, ObjectChange
|
from extras.models import CustomField, CustomFieldValue, ObjectChange
|
||||||
from utilities.testing import APITestCase
|
from utilities.testing import APITestCase
|
||||||
@ -17,7 +18,7 @@ class ChangeLogTest(APITestCase):
|
|||||||
# Create a custom field on the Site model
|
# Create a custom field on the Site model
|
||||||
ct = ContentType.objects.get_for_model(Site)
|
ct = ContentType.objects.get_for_model(Site)
|
||||||
cf = CustomField(
|
cf = CustomField(
|
||||||
type=CF_TYPE_TEXT,
|
type=CustomFieldTypeChoices.TYPE_TEXT,
|
||||||
name='my_field',
|
name='my_field',
|
||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
|
@ -6,7 +6,7 @@ from django.urls import reverse
|
|||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
from dcim.models import Site
|
from dcim.models import Site
|
||||||
from extras.constants import CF_TYPE_TEXT, CF_TYPE_INTEGER, CF_TYPE_BOOLEAN, CF_TYPE_DATE, CF_TYPE_SELECT, CF_TYPE_URL, CF_TYPE_SELECT
|
from extras.choices import *
|
||||||
from extras.models import CustomField, CustomFieldValue, CustomFieldChoice
|
from extras.models import CustomField, CustomFieldValue, CustomFieldChoice
|
||||||
from utilities.testing import APITestCase
|
from utilities.testing import APITestCase
|
||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
@ -25,13 +25,13 @@ class CustomFieldTest(TestCase):
|
|||||||
def test_simple_fields(self):
|
def test_simple_fields(self):
|
||||||
|
|
||||||
DATA = (
|
DATA = (
|
||||||
{'field_type': CF_TYPE_TEXT, 'field_value': 'Foobar!', 'empty_value': ''},
|
{'field_type': CustomFieldTypeChoices.TYPE_TEXT, 'field_value': 'Foobar!', 'empty_value': ''},
|
||||||
{'field_type': CF_TYPE_INTEGER, 'field_value': 0, 'empty_value': None},
|
{'field_type': CustomFieldTypeChoices.TYPE_INTEGER, 'field_value': 0, 'empty_value': None},
|
||||||
{'field_type': CF_TYPE_INTEGER, 'field_value': 42, 'empty_value': None},
|
{'field_type': CustomFieldTypeChoices.TYPE_INTEGER, 'field_value': 42, 'empty_value': None},
|
||||||
{'field_type': CF_TYPE_BOOLEAN, 'field_value': True, 'empty_value': None},
|
{'field_type': CustomFieldTypeChoices.TYPE_BOOLEAN, 'field_value': True, 'empty_value': None},
|
||||||
{'field_type': CF_TYPE_BOOLEAN, 'field_value': False, 'empty_value': None},
|
{'field_type': CustomFieldTypeChoices.TYPE_BOOLEAN, 'field_value': False, 'empty_value': None},
|
||||||
{'field_type': CF_TYPE_DATE, 'field_value': date(2016, 6, 23), 'empty_value': None},
|
{'field_type': CustomFieldTypeChoices.TYPE_DATE, 'field_value': date(2016, 6, 23), 'empty_value': None},
|
||||||
{'field_type': CF_TYPE_URL, 'field_value': 'http://example.com/', 'empty_value': ''},
|
{'field_type': CustomFieldTypeChoices.TYPE_URL, 'field_value': 'http://example.com/', 'empty_value': ''},
|
||||||
)
|
)
|
||||||
|
|
||||||
obj_type = ContentType.objects.get_for_model(Site)
|
obj_type = ContentType.objects.get_for_model(Site)
|
||||||
@ -67,7 +67,7 @@ class CustomFieldTest(TestCase):
|
|||||||
obj_type = ContentType.objects.get_for_model(Site)
|
obj_type = ContentType.objects.get_for_model(Site)
|
||||||
|
|
||||||
# Create a custom field
|
# Create a custom field
|
||||||
cf = CustomField(type=CF_TYPE_SELECT, name='my_field', required=False)
|
cf = CustomField(type=CustomFieldTypeChoices.TYPE_SELECT, name='my_field', required=False)
|
||||||
cf.save()
|
cf.save()
|
||||||
cf.obj_type.set([obj_type])
|
cf.obj_type.set([obj_type])
|
||||||
cf.save()
|
cf.save()
|
||||||
@ -107,37 +107,37 @@ class CustomFieldAPITest(APITestCase):
|
|||||||
content_type = ContentType.objects.get_for_model(Site)
|
content_type = ContentType.objects.get_for_model(Site)
|
||||||
|
|
||||||
# Text custom field
|
# Text custom field
|
||||||
self.cf_text = CustomField(type=CF_TYPE_TEXT, name='magic_word')
|
self.cf_text = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='magic_word')
|
||||||
self.cf_text.save()
|
self.cf_text.save()
|
||||||
self.cf_text.obj_type.set([content_type])
|
self.cf_text.obj_type.set([content_type])
|
||||||
self.cf_text.save()
|
self.cf_text.save()
|
||||||
|
|
||||||
# Integer custom field
|
# Integer custom field
|
||||||
self.cf_integer = CustomField(type=CF_TYPE_INTEGER, name='magic_number')
|
self.cf_integer = CustomField(type=CustomFieldTypeChoices.TYPE_INTEGER, name='magic_number')
|
||||||
self.cf_integer.save()
|
self.cf_integer.save()
|
||||||
self.cf_integer.obj_type.set([content_type])
|
self.cf_integer.obj_type.set([content_type])
|
||||||
self.cf_integer.save()
|
self.cf_integer.save()
|
||||||
|
|
||||||
# Boolean custom field
|
# Boolean custom field
|
||||||
self.cf_boolean = CustomField(type=CF_TYPE_BOOLEAN, name='is_magic')
|
self.cf_boolean = CustomField(type=CustomFieldTypeChoices.TYPE_BOOLEAN, name='is_magic')
|
||||||
self.cf_boolean.save()
|
self.cf_boolean.save()
|
||||||
self.cf_boolean.obj_type.set([content_type])
|
self.cf_boolean.obj_type.set([content_type])
|
||||||
self.cf_boolean.save()
|
self.cf_boolean.save()
|
||||||
|
|
||||||
# Date custom field
|
# Date custom field
|
||||||
self.cf_date = CustomField(type=CF_TYPE_DATE, name='magic_date')
|
self.cf_date = CustomField(type=CustomFieldTypeChoices.TYPE_DATE, name='magic_date')
|
||||||
self.cf_date.save()
|
self.cf_date.save()
|
||||||
self.cf_date.obj_type.set([content_type])
|
self.cf_date.obj_type.set([content_type])
|
||||||
self.cf_date.save()
|
self.cf_date.save()
|
||||||
|
|
||||||
# URL custom field
|
# URL custom field
|
||||||
self.cf_url = CustomField(type=CF_TYPE_URL, name='magic_url')
|
self.cf_url = CustomField(type=CustomFieldTypeChoices.TYPE_URL, name='magic_url')
|
||||||
self.cf_url.save()
|
self.cf_url.save()
|
||||||
self.cf_url.obj_type.set([content_type])
|
self.cf_url.obj_type.set([content_type])
|
||||||
self.cf_url.save()
|
self.cf_url.save()
|
||||||
|
|
||||||
# Select custom field
|
# Select custom field
|
||||||
self.cf_select = CustomField(type=CF_TYPE_SELECT, name='magic_choice')
|
self.cf_select = CustomField(type=CustomFieldTypeChoices.TYPE_SELECT, name='magic_choice')
|
||||||
self.cf_select.save()
|
self.cf_select.save()
|
||||||
self.cf_select.obj_type.set([content_type])
|
self.cf_select.obj_type.set([content_type])
|
||||||
self.cf_select.save()
|
self.cf_select.save()
|
||||||
@ -308,8 +308,8 @@ class CustomFieldChoiceAPITest(APITestCase):
|
|||||||
|
|
||||||
vm_content_type = ContentType.objects.get_for_model(VirtualMachine)
|
vm_content_type = ContentType.objects.get_for_model(VirtualMachine)
|
||||||
|
|
||||||
self.cf_1 = CustomField.objects.create(name="cf_1", type=CF_TYPE_SELECT)
|
self.cf_1 = CustomField.objects.create(name="cf_1", type=CustomFieldTypeChoices.TYPE_SELECT)
|
||||||
self.cf_2 = CustomField.objects.create(name="cf_2", type=CF_TYPE_SELECT)
|
self.cf_2 = CustomField.objects.create(name="cf_2", type=CustomFieldTypeChoices.TYPE_SELECT)
|
||||||
|
|
||||||
self.cf_choice_1 = CustomFieldChoice.objects.create(field=self.cf_1, value="cf_field_1", weight=100)
|
self.cf_choice_1 = CustomFieldChoice.objects.create(field=self.cf_1, value="cf_field_1", weight=100)
|
||||||
self.cf_choice_2 = CustomFieldChoice.objects.create(field=self.cf_1, value="cf_field_2", weight=50)
|
self.cf_choice_2 = CustomFieldChoice.objects.create(field=self.cf_1, value="cf_field_2", weight=50)
|
||||||
|
Reference in New Issue
Block a user