mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-25 01:48:38 -06:00
Move form field generation logic to CustomField class
This commit is contained in:
parent
9929a05bfe
commit
585ea71d1a
@ -3,15 +3,14 @@ from collections import OrderedDict
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
|
||||||
from taggit.forms import TagField
|
from taggit.forms import TagField
|
||||||
|
|
||||||
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 utilities.forms import (
|
from utilities.forms import (
|
||||||
add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect,
|
add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect,
|
||||||
CommentField, ContentTypeSelect, DatePicker, DateTimePicker, FilterChoiceField, LaxURLField, JSONField, SlugField,
|
CommentField, ContentTypeSelect, DateTimePicker, FilterChoiceField, JSONField, SlugField, StaticSelect2,
|
||||||
StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES,
|
BOOLEAN_WITH_BLANK_CHOICES,
|
||||||
)
|
)
|
||||||
from .choices import *
|
from .choices import *
|
||||||
from .models import ConfigContext, CustomField, CustomFieldValue, ImageAttachment, ObjectChange, Tag
|
from .models import ConfigContext, CustomField, CustomFieldValue, ImageAttachment, ObjectChange, Tag
|
||||||
@ -32,63 +31,7 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F
|
|||||||
|
|
||||||
for cf in custom_fields:
|
for cf in custom_fields:
|
||||||
field_name = 'cf_{}'.format(str(cf.name))
|
field_name = 'cf_{}'.format(str(cf.name))
|
||||||
initial = cf.default if not bulk_edit else None
|
field_dict[field_name] = cf.to_form_field(set_initial=not bulk_edit)
|
||||||
|
|
||||||
# Integer
|
|
||||||
if cf.type == CustomFieldTypeChoices.TYPE_INTEGER:
|
|
||||||
field = forms.IntegerField(required=cf.required, initial=initial)
|
|
||||||
|
|
||||||
# Boolean
|
|
||||||
elif cf.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
|
|
||||||
choices = (
|
|
||||||
(None, '---------'),
|
|
||||||
(1, 'True'),
|
|
||||||
(0, 'False'),
|
|
||||||
)
|
|
||||||
if initial is not None and initial.lower() in ['true', 'yes', '1']:
|
|
||||||
initial = 1
|
|
||||||
elif initial is not None and initial.lower() in ['false', 'no', '0']:
|
|
||||||
initial = 0
|
|
||||||
else:
|
|
||||||
initial = None
|
|
||||||
field = forms.NullBooleanField(
|
|
||||||
required=cf.required, initial=initial, widget=StaticSelect2(choices=choices)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Date
|
|
||||||
elif cf.type == CustomFieldTypeChoices.TYPE_DATE:
|
|
||||||
field = forms.DateField(required=cf.required, initial=initial, widget=DatePicker())
|
|
||||||
|
|
||||||
# Select
|
|
||||||
elif cf.type == CustomFieldTypeChoices.TYPE_SELECT:
|
|
||||||
choices = [(cfc.pk, cfc.value) for cfc in cf.choices.all()]
|
|
||||||
if not cf.required or bulk_edit or filterable_only:
|
|
||||||
choices = [(None, '---------')] + choices
|
|
||||||
# Check for a default choice
|
|
||||||
default_choice = None
|
|
||||||
if initial:
|
|
||||||
try:
|
|
||||||
default_choice = cf.choices.get(value=initial).pk
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
pass
|
|
||||||
field = forms.TypedChoiceField(
|
|
||||||
choices=choices, coerce=int, required=cf.required, initial=default_choice, widget=StaticSelect2()
|
|
||||||
)
|
|
||||||
|
|
||||||
# URL
|
|
||||||
elif cf.type == CustomFieldTypeChoices.TYPE_URL:
|
|
||||||
field = LaxURLField(required=cf.required, initial=initial)
|
|
||||||
|
|
||||||
# Text
|
|
||||||
else:
|
|
||||||
field = forms.CharField(max_length=255, required=cf.required, initial=initial)
|
|
||||||
|
|
||||||
field.model = cf
|
|
||||||
field.label = cf.label if cf.label else cf.name.replace('_', ' ').capitalize()
|
|
||||||
if cf.description:
|
|
||||||
field.help_text = cf.description
|
|
||||||
|
|
||||||
field_dict[field_name] = field
|
|
||||||
|
|
||||||
return field_dict
|
return field_dict
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
|
from django import forms
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
@ -14,6 +15,7 @@ from django.utils.text import slugify
|
|||||||
from taggit.models import TagBase, GenericTaggedItemBase
|
from taggit.models import TagBase, GenericTaggedItemBase
|
||||||
|
|
||||||
from utilities.fields import ColorField
|
from utilities.fields import ColorField
|
||||||
|
from utilities.forms import DatePicker, LaxURLField, StaticSelect2, add_blank_choice
|
||||||
from utilities.utils import deepmerge, render_jinja2
|
from utilities.utils import deepmerge, render_jinja2
|
||||||
from .choices import *
|
from .choices import *
|
||||||
from .constants import *
|
from .constants import *
|
||||||
@ -280,6 +282,70 @@ class CustomField(models.Model):
|
|||||||
return self.choices.get(pk=int(serialized_value))
|
return self.choices.get(pk=int(serialized_value))
|
||||||
return serialized_value
|
return serialized_value
|
||||||
|
|
||||||
|
def to_form_field(self, set_initial=True):
|
||||||
|
"""
|
||||||
|
Return a form field suitable for setting a CustomField's value for an object.
|
||||||
|
|
||||||
|
set_initial: Set initial date for the field. This should be false when generating a field for bulk editing.
|
||||||
|
"""
|
||||||
|
initial = self.default if set_initial else None
|
||||||
|
|
||||||
|
# Integer
|
||||||
|
if self.type == CustomFieldTypeChoices.TYPE_INTEGER:
|
||||||
|
field = forms.IntegerField(required=self.required, initial=initial)
|
||||||
|
|
||||||
|
# Boolean
|
||||||
|
elif self.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
|
||||||
|
choices = (
|
||||||
|
(None, '---------'),
|
||||||
|
(1, 'True'),
|
||||||
|
(0, 'False'),
|
||||||
|
)
|
||||||
|
if initial is not None and initial.lower() in ['true', 'yes', '1']:
|
||||||
|
initial = 1
|
||||||
|
elif initial is not None and initial.lower() in ['false', 'no', '0']:
|
||||||
|
initial = 0
|
||||||
|
else:
|
||||||
|
initial = None
|
||||||
|
field = forms.NullBooleanField(
|
||||||
|
required=self.required, initial=initial, widget=StaticSelect2(choices=choices)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Date
|
||||||
|
elif self.type == CustomFieldTypeChoices.TYPE_DATE:
|
||||||
|
field = forms.DateField(required=self.required, initial=initial, widget=DatePicker())
|
||||||
|
|
||||||
|
# Select
|
||||||
|
elif self.type == CustomFieldTypeChoices.TYPE_SELECT:
|
||||||
|
choices = [(cfc.pk, cfc.value) for cfc in self.choices.all()]
|
||||||
|
# TODO: Accommodate bulk edit/filtering
|
||||||
|
# if not self.required or bulk_edit or filterable_only:
|
||||||
|
if not self.required:
|
||||||
|
choices = add_blank_choice(choices)
|
||||||
|
# Set the initial value to the PK of the default choice, if any
|
||||||
|
if set_initial:
|
||||||
|
default_choice = self.choices.filter(value=self.default).first()
|
||||||
|
if default_choice:
|
||||||
|
initial = default_choice.pk
|
||||||
|
field = forms.TypedChoiceField(
|
||||||
|
choices=choices, coerce=int, required=self.required, initial=initial, widget=StaticSelect2()
|
||||||
|
)
|
||||||
|
|
||||||
|
# URL
|
||||||
|
elif self.type == CustomFieldTypeChoices.TYPE_URL:
|
||||||
|
field = LaxURLField(required=self.required, initial=initial)
|
||||||
|
|
||||||
|
# Text
|
||||||
|
else:
|
||||||
|
field = forms.CharField(max_length=255, required=self.required, initial=initial)
|
||||||
|
|
||||||
|
field.model = self
|
||||||
|
field.label = self.label if self.label else self.name.replace('_', ' ').capitalize()
|
||||||
|
if self.description:
|
||||||
|
field.help_text = self.description
|
||||||
|
|
||||||
|
return field
|
||||||
|
|
||||||
|
|
||||||
class CustomFieldValue(models.Model):
|
class CustomFieldValue(models.Model):
|
||||||
field = models.ForeignKey(
|
field = models.ForeignKey(
|
||||||
|
Loading…
Reference in New Issue
Block a user