mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
199 lines
5.4 KiB
Python
199 lines
5.4 KiB
Python
import json
|
|
|
|
from django import forms
|
|
from django.conf import settings
|
|
from django.contrib.postgres.forms import SimpleArrayField
|
|
|
|
from utilities.choices import ColorChoices
|
|
from .utils import add_blank_choice, parse_numeric_range
|
|
|
|
__all__ = (
|
|
'APISelect',
|
|
'APISelectMultiple',
|
|
'BulkEditNullBooleanSelect',
|
|
'ColorSelect',
|
|
'ContentTypeSelect',
|
|
'DatePicker',
|
|
'DateTimePicker',
|
|
'NumericArrayField',
|
|
'SelectSpeedWidget',
|
|
'SelectWithDisabled',
|
|
'SelectWithPK',
|
|
'SlugWidget',
|
|
'SmallTextarea',
|
|
'StaticSelect2',
|
|
'StaticSelect2Multiple',
|
|
'TimePicker',
|
|
)
|
|
|
|
|
|
class SmallTextarea(forms.Textarea):
|
|
"""
|
|
Subclass used for rendering a smaller textarea element.
|
|
"""
|
|
pass
|
|
|
|
|
|
class SlugWidget(forms.TextInput):
|
|
"""
|
|
Subclass TextInput and add a slug regeneration button next to the form field.
|
|
"""
|
|
template_name = 'widgets/sluginput.html'
|
|
|
|
|
|
class ColorSelect(forms.Select):
|
|
"""
|
|
Extends the built-in Select widget to colorize each <option>.
|
|
"""
|
|
option_template_name = 'widgets/colorselect_option.html'
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
kwargs['choices'] = add_blank_choice(ColorChoices)
|
|
super().__init__(*args, **kwargs)
|
|
self.attrs['class'] = 'netbox-select2-color-picker'
|
|
|
|
|
|
class BulkEditNullBooleanSelect(forms.NullBooleanSelect):
|
|
"""
|
|
A Select widget for NullBooleanFields
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Override the built-in choice labels
|
|
self.choices = (
|
|
('1', '---------'),
|
|
('2', 'Yes'),
|
|
('3', 'No'),
|
|
)
|
|
self.attrs['class'] = 'netbox-select2-static'
|
|
|
|
|
|
class SelectWithDisabled(forms.Select):
|
|
"""
|
|
Modified the stock Select widget to accept choices using a dict() for a label. The dict for each option must include
|
|
'label' (string) and 'disabled' (boolean).
|
|
"""
|
|
option_template_name = 'widgets/selectwithdisabled_option.html'
|
|
|
|
|
|
class StaticSelect2(SelectWithDisabled):
|
|
"""
|
|
A static <select> form widget using the Select2 library.
|
|
"""
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.attrs['class'] = 'netbox-select2-static'
|
|
|
|
|
|
class StaticSelect2Multiple(StaticSelect2, forms.SelectMultiple):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.attrs['data-multiple'] = 1
|
|
|
|
|
|
class SelectWithPK(StaticSelect2):
|
|
"""
|
|
Include the primary key of each option in the option label (e.g. "Router7 (4721)").
|
|
"""
|
|
option_template_name = 'widgets/select_option_with_pk.html'
|
|
|
|
|
|
class ContentTypeSelect(StaticSelect2):
|
|
"""
|
|
Appends an `api-value` attribute equal to the slugified model name for each ContentType. For example:
|
|
<option value="37" api-value="console-server-port">console server port</option>
|
|
This attribute can be used to reference the relevant API endpoint for a particular ContentType.
|
|
"""
|
|
option_template_name = 'widgets/select_contenttype.html'
|
|
|
|
|
|
class SelectSpeedWidget(forms.NumberInput):
|
|
"""
|
|
Speed field with dropdown selections for convenience.
|
|
"""
|
|
template_name = 'widgets/select_speed.html'
|
|
|
|
|
|
class NumericArrayField(SimpleArrayField):
|
|
|
|
def to_python(self, value):
|
|
if not value:
|
|
return []
|
|
if isinstance(value, str):
|
|
value = ','.join([str(n) for n in parse_numeric_range(value)])
|
|
return super().to_python(value)
|
|
|
|
|
|
class APISelect(SelectWithDisabled):
|
|
"""
|
|
A select widget populated via an API call
|
|
|
|
:param api_url: API endpoint URL. Required if not set automatically by the parent field.
|
|
"""
|
|
def __init__(self, api_url=None, full=False, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.attrs['class'] = 'netbox-select2-api'
|
|
if api_url:
|
|
self.attrs['data-url'] = '/{}{}'.format(settings.BASE_PATH, api_url.lstrip('/')) # Inject BASE_PATH
|
|
|
|
def add_query_param(self, name, value):
|
|
"""
|
|
Add details for an additional query param in the form of a data-* JSON-encoded list attribute.
|
|
|
|
:param name: The name of the query param
|
|
:param value: The value of the query param
|
|
"""
|
|
key = f'data-query-param-{name}'
|
|
|
|
values = json.loads(self.attrs.get(key, '[]'))
|
|
if type(value) in (list, tuple):
|
|
values.extend([str(v) for v in value])
|
|
else:
|
|
values.append(str(value))
|
|
|
|
self.attrs[key] = json.dumps(values)
|
|
|
|
|
|
class APISelectMultiple(APISelect, forms.SelectMultiple):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.attrs['data-multiple'] = 1
|
|
|
|
|
|
class DatePicker(forms.TextInput):
|
|
"""
|
|
Date picker using Flatpickr.
|
|
"""
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.attrs['class'] = 'date-picker'
|
|
self.attrs['placeholder'] = 'YYYY-MM-DD'
|
|
|
|
|
|
class DateTimePicker(forms.TextInput):
|
|
"""
|
|
DateTime picker using Flatpickr.
|
|
"""
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.attrs['class'] = 'datetime-picker'
|
|
self.attrs['placeholder'] = 'YYYY-MM-DD hh:mm:ss'
|
|
|
|
|
|
class TimePicker(forms.TextInput):
|
|
"""
|
|
Time picker using Flatpickr.
|
|
"""
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.attrs['class'] = 'time-picker'
|
|
self.attrs['placeholder'] = 'hh:mm:ss'
|