mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-15 19:52:52 -06:00
10300 initial translation support use gettext
This commit is contained in:
parent
2cc2d2cc37
commit
6eba5d4d96
@ -1,5 +1,6 @@
|
||||
import django_filters
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.filtersets import CabledObjectFilterSet
|
||||
from dcim.models import Region, Site, SiteGroup
|
||||
@ -24,43 +25,43 @@ class ProviderFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
queryset=Region.objects.all(),
|
||||
field_name='circuits__terminations__site__region',
|
||||
lookup_expr='in',
|
||||
label='Region (ID)',
|
||||
label=_('Region (ID)'),
|
||||
)
|
||||
region = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='circuits__terminations__site__region',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Region (slug)',
|
||||
label=_('Region (slug)'),
|
||||
)
|
||||
site_group_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='circuits__terminations__site__group',
|
||||
lookup_expr='in',
|
||||
label='Site group (ID)',
|
||||
label=_('Site group (ID)'),
|
||||
)
|
||||
site_group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='circuits__terminations__site__group',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Site group (slug)',
|
||||
label=_('Site group (slug)'),
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='circuits__terminations__site',
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
label=_('Site'),
|
||||
)
|
||||
site = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='circuits__terminations__site__slug',
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
asn_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='asns',
|
||||
queryset=ASN.objects.all(),
|
||||
label='ASN (ID)',
|
||||
label=_('ASN (ID)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -80,13 +81,13 @@ class ProviderFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
class ProviderNetworkFilterSet(NetBoxModelFilterSet):
|
||||
provider_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Provider.objects.all(),
|
||||
label='Provider (ID)',
|
||||
label=_('Provider (ID)'),
|
||||
)
|
||||
provider = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='provider__slug',
|
||||
queryset=Provider.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Provider (slug)',
|
||||
label=_('Provider (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -114,28 +115,28 @@ class CircuitTypeFilterSet(OrganizationalModelFilterSet):
|
||||
class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
|
||||
provider_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Provider.objects.all(),
|
||||
label='Provider (ID)',
|
||||
label=_('Provider (ID)'),
|
||||
)
|
||||
provider = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='provider__slug',
|
||||
queryset=Provider.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Provider (slug)',
|
||||
label=_('Provider (slug)'),
|
||||
)
|
||||
provider_network_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='terminations__provider_network',
|
||||
queryset=ProviderNetwork.objects.all(),
|
||||
label='ProviderNetwork (ID)',
|
||||
label=_('ProviderNetwork (ID)'),
|
||||
)
|
||||
type_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=CircuitType.objects.all(),
|
||||
label='Circuit type (ID)',
|
||||
label=_('Circuit type (ID)'),
|
||||
)
|
||||
type = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='type__slug',
|
||||
queryset=CircuitType.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Circuit type (slug)',
|
||||
label=_('Circuit type (slug)'),
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=CircuitStatusChoices,
|
||||
@ -145,38 +146,38 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
|
||||
queryset=Region.objects.all(),
|
||||
field_name='terminations__site__region',
|
||||
lookup_expr='in',
|
||||
label='Region (ID)',
|
||||
label=_('Region (ID)'),
|
||||
)
|
||||
region = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='terminations__site__region',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Region (slug)',
|
||||
label=_('Region (slug)'),
|
||||
)
|
||||
site_group_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='terminations__site__group',
|
||||
lookup_expr='in',
|
||||
label='Site group (ID)',
|
||||
label=_('Site group (ID)'),
|
||||
)
|
||||
site_group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='terminations__site__group',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Site group (slug)',
|
||||
label=_('Site group (slug)'),
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='terminations__site',
|
||||
queryset=Site.objects.all(),
|
||||
label='Site (ID)',
|
||||
label=_('Site (ID)'),
|
||||
)
|
||||
site = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='terminations__site__slug',
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -199,25 +200,25 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
|
||||
class CircuitTerminationFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
circuit_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Circuit.objects.all(),
|
||||
label='Circuit',
|
||||
label=_('Circuit'),
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site (ID)',
|
||||
label=_('Site (ID)'),
|
||||
)
|
||||
site = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='site__slug',
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
provider_network_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ProviderNetwork.objects.all(),
|
||||
label='ProviderNetwork (ID)',
|
||||
label=_('ProviderNetwork (ID)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -28,7 +28,7 @@ class ProviderBulkEditForm(NetBoxModelBulkEditForm):
|
||||
account = forms.CharField(
|
||||
max_length=30,
|
||||
required=False,
|
||||
label='Account number'
|
||||
label=_('Account number')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -36,7 +36,7 @@ class ProviderBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
comments = CommentField(
|
||||
widget=SmallTextarea,
|
||||
label='Comments'
|
||||
label=_('Comments')
|
||||
)
|
||||
|
||||
model = Provider
|
||||
@ -56,7 +56,7 @@ class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm):
|
||||
service_id = forms.CharField(
|
||||
max_length=100,
|
||||
required=False,
|
||||
label='Service ID'
|
||||
label=_('Service ID')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -64,7 +64,7 @@ class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
comments = CommentField(
|
||||
widget=SmallTextarea,
|
||||
label='Comments'
|
||||
label=_('Comments')
|
||||
)
|
||||
|
||||
model = ProviderNetwork
|
||||
@ -118,7 +118,7 @@ class CircuitBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
commit_rate = forms.IntegerField(
|
||||
required=False,
|
||||
label='Commit rate (Kbps)'
|
||||
label=_('Commit rate (Kbps)')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=100,
|
||||
@ -126,7 +126,7 @@ class CircuitBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
comments = CommentField(
|
||||
widget=SmallTextarea,
|
||||
label='Comments'
|
||||
label=_('Comments')
|
||||
)
|
||||
|
||||
model = Circuit
|
||||
|
@ -1,5 +1,6 @@
|
||||
from circuits.choices import CircuitStatusChoices
|
||||
from circuits.models import *
|
||||
from django.utils.translation import gettext as _
|
||||
from netbox.forms import NetBoxModelCSVForm
|
||||
from tenancy.models import Tenant
|
||||
from utilities.forms import CSVChoiceField, CSVModelChoiceField, SlugField
|
||||
@ -26,7 +27,7 @@ class ProviderNetworkCSVForm(NetBoxModelCSVForm):
|
||||
provider = CSVModelChoiceField(
|
||||
queryset=Provider.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Assigned provider'
|
||||
help_text=_('Assigned provider')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -43,7 +44,7 @@ class CircuitTypeCSVForm(NetBoxModelCSVForm):
|
||||
model = CircuitType
|
||||
fields = ('name', 'slug', 'description', 'tags')
|
||||
help_texts = {
|
||||
'name': 'Name of circuit type',
|
||||
'name': _('Name of circuit type'),
|
||||
}
|
||||
|
||||
|
||||
@ -51,22 +52,22 @@ class CircuitCSVForm(NetBoxModelCSVForm):
|
||||
provider = CSVModelChoiceField(
|
||||
queryset=Provider.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Assigned provider'
|
||||
help_text=_('Assigned provider')
|
||||
)
|
||||
type = CSVModelChoiceField(
|
||||
queryset=CircuitType.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Type of circuit'
|
||||
help_text=_('Type of circuit')
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=CircuitStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -39,7 +39,7 @@ class ProviderForm(NetBoxModelForm):
|
||||
'name', 'slug', 'account', 'asns', 'description', 'comments', 'tags',
|
||||
]
|
||||
help_texts = {
|
||||
'name': "Full name of the provider",
|
||||
'name': _("Full name of the provider"),
|
||||
}
|
||||
|
||||
|
||||
@ -98,8 +98,8 @@ class CircuitForm(TenancyForm, NetBoxModelForm):
|
||||
'tenant_group', 'tenant', 'comments', 'tags',
|
||||
]
|
||||
help_texts = {
|
||||
'cid': "Unique circuit ID",
|
||||
'commit_rate': "Committed rate",
|
||||
'cid': _("Unique circuit ID"),
|
||||
'commit_rate': _("Committed rate"),
|
||||
}
|
||||
widgets = {
|
||||
'status': StaticSelect(),
|
||||
@ -157,9 +157,9 @@ class CircuitTerminationForm(NetBoxModelForm):
|
||||
'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description', 'tags',
|
||||
]
|
||||
help_texts = {
|
||||
'port_speed': "Physical circuit speed",
|
||||
'xconnect_id': "ID of the local cross-connect",
|
||||
'pp_info': "Patch panel ID and port number(s)"
|
||||
'port_speed': _("Physical circuit speed"),
|
||||
'xconnect_id': _("ID of the local cross-connect"),
|
||||
'pp_info': _("Patch panel ID and port number(s)")
|
||||
}
|
||||
widgets = {
|
||||
'term_side': StaticSelect(),
|
||||
|
@ -3,6 +3,7 @@ from django.contrib.contenttypes.fields import GenericRelation
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from circuits.choices import *
|
||||
from dcim.models import CabledObjectModel
|
||||
@ -168,7 +169,7 @@ class CircuitTermination(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Upstream speed (Kbps)',
|
||||
help_text='Upstream speed, if different from port speed'
|
||||
help_text=_('Upstream speed, if different from port speed')
|
||||
)
|
||||
xconnect_id = models.CharField(
|
||||
max_length=50,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import decimal
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import gettext as _
|
||||
from drf_yasg.utils import swagger_serializer_method
|
||||
from rest_framework import serializers
|
||||
from timezone_field.rest_framework import TimeZoneSerializerField
|
||||
@ -197,7 +198,7 @@ class RackSerializer(NetBoxModelSerializer):
|
||||
status = ChoiceField(choices=RackStatusChoices, required=False)
|
||||
role = NestedRackRoleSerializer(required=False, allow_null=True)
|
||||
type = ChoiceField(choices=RackTypeChoices, allow_blank=True, required=False)
|
||||
facility_id = serializers.CharField(max_length=50, allow_blank=True, allow_null=True, label='Facility ID',
|
||||
facility_id = serializers.CharField(max_length=50, allow_blank=True, allow_null=True, label=_('Facility ID'),
|
||||
default=None)
|
||||
width = ChoiceField(choices=RackWidthChoices, required=False)
|
||||
outer_unit = ChoiceField(choices=RackDimensionUnitChoices, allow_blank=True, required=False)
|
||||
@ -311,7 +312,7 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
|
||||
u_height = serializers.DecimalField(
|
||||
max_digits=4,
|
||||
decimal_places=1,
|
||||
label='Position (U)',
|
||||
label=_('Position (U)'),
|
||||
min_value=0,
|
||||
default=1.0
|
||||
)
|
||||
@ -636,7 +637,7 @@ class DeviceSerializer(NetBoxModelSerializer):
|
||||
max_digits=4,
|
||||
decimal_places=1,
|
||||
allow_null=True,
|
||||
label='Position (U)',
|
||||
label=_('Position (U)'),
|
||||
min_value=decimal.Decimal(0.5),
|
||||
default=None
|
||||
)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
from django import forms
|
||||
|
||||
from dcim.models import *
|
||||
from django.utils.translation import gettext as _
|
||||
from extras.forms import CustomFieldsMixin
|
||||
from extras.models import Tag
|
||||
from utilities.forms import BootstrapMixin, DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model
|
||||
@ -105,9 +106,9 @@ class ModuleBayBulkCreateForm(DeviceBulkAddComponentForm):
|
||||
field_order = ('name', 'label', 'position_pattern', 'description', 'tags')
|
||||
replication_fields = ('name', 'label', 'position')
|
||||
position_pattern = ExpandableNameField(
|
||||
label='Position',
|
||||
label=_('Position'),
|
||||
required=False,
|
||||
help_text='Alphanumeric ranges are supported. (Must match the number of names being created.)'
|
||||
help_text=_('Alphanumeric ranges are supported. (Must match the number of names being created.)')
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import gettext as _
|
||||
from timezone_field import TimeZoneFormField
|
||||
|
||||
from dcim.choices import *
|
||||
@ -126,7 +126,7 @@ class SiteBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
contact_email = forms.EmailField(
|
||||
required=False,
|
||||
label='Contact E-mail'
|
||||
label=_('Contact E-mail')
|
||||
)
|
||||
time_zone = TimeZoneFormField(
|
||||
choices=add_blank_choice(TimeZoneFormField().choices),
|
||||
@ -248,7 +248,7 @@ class RackBulkEditForm(NetBoxModelBulkEditForm):
|
||||
serial = forms.CharField(
|
||||
max_length=50,
|
||||
required=False,
|
||||
label='Serial Number'
|
||||
label=_('Serial Number')
|
||||
)
|
||||
asset_tag = forms.CharField(
|
||||
max_length=50,
|
||||
@ -266,12 +266,12 @@ class RackBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
u_height = forms.IntegerField(
|
||||
required=False,
|
||||
label='Height (U)'
|
||||
label=_('Height (U)')
|
||||
)
|
||||
desc_units = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect,
|
||||
label='Descending units'
|
||||
label=_('Descending units')
|
||||
)
|
||||
outer_width = forms.IntegerField(
|
||||
required=False,
|
||||
@ -380,7 +380,7 @@ class DeviceTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
is_full_depth = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect(),
|
||||
label='Is full depth'
|
||||
label=_('Is full depth')
|
||||
)
|
||||
airflow = forms.ChoiceField(
|
||||
choices=add_blank_choice(DeviceAirflowChoices),
|
||||
@ -456,7 +456,7 @@ class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
vm_role = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect,
|
||||
label='VM role'
|
||||
label=_('VM role')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -540,7 +540,7 @@ class DeviceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
serial = forms.CharField(
|
||||
max_length=50,
|
||||
required=False,
|
||||
label='Serial Number'
|
||||
label=_('Serial Number')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -577,7 +577,7 @@ class ModuleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
serial = forms.CharField(
|
||||
max_length=50,
|
||||
required=False,
|
||||
label='Serial Number'
|
||||
label=_('Serial Number')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -767,7 +767,7 @@ class PowerFeedBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
comments = CommentField(
|
||||
widget=SmallTextarea,
|
||||
label='Comments'
|
||||
label=_('Comments')
|
||||
)
|
||||
|
||||
model = PowerFeed
|
||||
@ -838,12 +838,12 @@ class PowerPortTemplateBulkEditForm(BulkEditForm):
|
||||
maximum_draw = forms.IntegerField(
|
||||
min_value=1,
|
||||
required=False,
|
||||
help_text="Maximum power draw (watts)"
|
||||
help_text=_("Maximum power draw (watts)")
|
||||
)
|
||||
allocated_draw = forms.IntegerField(
|
||||
min_value=1,
|
||||
required=False,
|
||||
help_text="Allocated power draw (watts)"
|
||||
help_text=_("Allocated power draw (watts)")
|
||||
)
|
||||
description = forms.CharField(
|
||||
required=False
|
||||
@ -916,7 +916,7 @@ class InterfaceTemplateBulkEditForm(BulkEditForm):
|
||||
mgmt_only = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect,
|
||||
label='Management only'
|
||||
label=_('Management only')
|
||||
)
|
||||
description = forms.CharField(
|
||||
required=False
|
||||
@ -926,14 +926,14 @@ class InterfaceTemplateBulkEditForm(BulkEditForm):
|
||||
required=False,
|
||||
initial='',
|
||||
widget=StaticSelect(),
|
||||
label='PoE mode'
|
||||
label=_('PoE mode')
|
||||
)
|
||||
poe_type = forms.ChoiceField(
|
||||
choices=add_blank_choice(InterfacePoETypeChoices),
|
||||
required=False,
|
||||
initial='',
|
||||
widget=StaticSelect(),
|
||||
label='PoE type'
|
||||
label=_('PoE type')
|
||||
)
|
||||
|
||||
nullable_fields = ('label', 'description', 'poe_mode', 'poe_type')
|
||||
@ -1174,31 +1174,31 @@ class InterfaceBulkEditForm(
|
||||
query_params={
|
||||
'type': 'lag',
|
||||
},
|
||||
label='LAG'
|
||||
label=_('LAG')
|
||||
)
|
||||
speed = forms.IntegerField(
|
||||
required=False,
|
||||
widget=SelectSpeedWidget(),
|
||||
label='Speed'
|
||||
label=_('Speed')
|
||||
)
|
||||
mgmt_only = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect,
|
||||
label='Management only'
|
||||
label=_('Management only')
|
||||
)
|
||||
poe_mode = forms.ChoiceField(
|
||||
choices=add_blank_choice(InterfacePoEModeChoices),
|
||||
required=False,
|
||||
initial='',
|
||||
widget=StaticSelect(),
|
||||
label='PoE mode'
|
||||
label=_('PoE mode')
|
||||
)
|
||||
poe_type = forms.ChoiceField(
|
||||
choices=add_blank_choice(InterfacePoETypeChoices),
|
||||
required=False,
|
||||
initial='',
|
||||
widget=StaticSelect(),
|
||||
label='PoE type'
|
||||
label=_('PoE type')
|
||||
)
|
||||
mark_connected = forms.NullBooleanField(
|
||||
required=False,
|
||||
@ -1213,7 +1213,7 @@ class InterfaceBulkEditForm(
|
||||
vlan_group = DynamicModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
label='VLAN group'
|
||||
label=_('VLAN group')
|
||||
)
|
||||
untagged_vlan = DynamicModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
@ -1221,7 +1221,7 @@ class InterfaceBulkEditForm(
|
||||
query_params={
|
||||
'group_id': '$vlan_group',
|
||||
},
|
||||
label='Untagged VLAN'
|
||||
label=_('Untagged VLAN')
|
||||
)
|
||||
tagged_vlans = DynamicModelMultipleChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
@ -1229,12 +1229,12 @@ class InterfaceBulkEditForm(
|
||||
query_params={
|
||||
'group_id': '$vlan_group',
|
||||
},
|
||||
label='Tagged VLANs'
|
||||
label=_('Tagged VLANs')
|
||||
)
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
|
||||
model = Interface
|
||||
|
@ -3,6 +3,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.postgres.forms.array import SimpleArrayField
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.choices import *
|
||||
from dcim.constants import *
|
||||
@ -52,7 +53,7 @@ class RegionCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Region.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Name of parent region'
|
||||
help_text=_('Name of parent region')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -65,7 +66,7 @@ class SiteGroupCSVForm(NetBoxModelCSVForm):
|
||||
queryset=SiteGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Name of parent site group'
|
||||
help_text=_('Name of parent site group')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -76,25 +77,25 @@ class SiteGroupCSVForm(NetBoxModelCSVForm):
|
||||
class SiteCSVForm(NetBoxModelCSVForm):
|
||||
status = CSVChoiceField(
|
||||
choices=SiteStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
region = CSVModelChoiceField(
|
||||
queryset=Region.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned region'
|
||||
help_text=_('Assigned region')
|
||||
)
|
||||
group = CSVModelChoiceField(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned group'
|
||||
help_text=_('Assigned group')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -105,7 +106,7 @@ class SiteCSVForm(NetBoxModelCSVForm):
|
||||
)
|
||||
help_texts = {
|
||||
'time_zone': mark_safe(
|
||||
'Time zone (<a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">available options</a>)'
|
||||
_('Time zone (<a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">available options</a>)')
|
||||
)
|
||||
}
|
||||
|
||||
@ -114,26 +115,26 @@ class LocationCSVForm(NetBoxModelCSVForm):
|
||||
site = CSVModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Assigned site'
|
||||
help_text=_('Assigned site')
|
||||
)
|
||||
parent = CSVModelChoiceField(
|
||||
queryset=Location.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent location',
|
||||
help_text=_('Parent location'),
|
||||
error_messages={
|
||||
'invalid_choice': 'Location not found.',
|
||||
'invalid_choice': _('Location not found.'),
|
||||
}
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=LocationStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -148,7 +149,7 @@ class RackRoleCSVForm(NetBoxModelCSVForm):
|
||||
model = RackRole
|
||||
fields = ('name', 'slug', 'color', 'description', 'tags')
|
||||
help_texts = {
|
||||
'color': mark_safe('RGB color in hexadecimal (e.g. <code>00ff00</code>)'),
|
||||
'color': mark_safe(_('RGB color in hexadecimal (e.g. <code>00ff00</code>)')),
|
||||
}
|
||||
|
||||
|
||||
@ -166,31 +167,31 @@ class RackCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Name of assigned tenant'
|
||||
help_text=_('Name of assigned tenant')
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=RackStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
role = CSVModelChoiceField(
|
||||
queryset=RackRole.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Name of assigned role'
|
||||
help_text=_('Name of assigned role')
|
||||
)
|
||||
type = CSVChoiceField(
|
||||
choices=RackTypeChoices,
|
||||
required=False,
|
||||
help_text='Rack type'
|
||||
help_text=_('Rack type')
|
||||
)
|
||||
width = forms.ChoiceField(
|
||||
choices=RackWidthChoices,
|
||||
help_text='Rail-to-rail width (in inches)'
|
||||
help_text=_('Rail-to-rail width (in inches)')
|
||||
)
|
||||
outer_unit = CSVChoiceField(
|
||||
choices=RackDimensionUnitChoices,
|
||||
required=False,
|
||||
help_text='Unit for outer dimensions'
|
||||
help_text=_('Unit for outer dimensions')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -215,29 +216,29 @@ class RackReservationCSVForm(NetBoxModelCSVForm):
|
||||
site = CSVModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Parent site'
|
||||
help_text=_('Parent site')
|
||||
)
|
||||
location = CSVModelChoiceField(
|
||||
queryset=Location.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text="Rack's location (if any)"
|
||||
help_text=_("Rack's location (if any)")
|
||||
)
|
||||
rack = CSVModelChoiceField(
|
||||
queryset=Rack.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Rack'
|
||||
help_text=_('Rack')
|
||||
)
|
||||
units = SimpleArrayField(
|
||||
base_field=forms.IntegerField(),
|
||||
required=True,
|
||||
help_text='Comma-separated list of individual unit numbers'
|
||||
help_text=_('Comma-separated list of individual unit numbers')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -275,7 +276,7 @@ class DeviceRoleCSVForm(NetBoxModelCSVForm):
|
||||
model = DeviceRole
|
||||
fields = ('name', 'slug', 'color', 'vm_role', 'description', 'tags')
|
||||
help_texts = {
|
||||
'color': mark_safe('RGB color in hexadecimal (e.g. <code>00ff00</code>)'),
|
||||
'color': mark_safe(_('RGB color in hexadecimal (e.g. <code>00ff00</code>)')),
|
||||
}
|
||||
|
||||
|
||||
@ -285,7 +286,7 @@ class PlatformCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Manufacturer.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Limit platform assignments to this manufacturer'
|
||||
help_text=_('Limit platform assignments to this manufacturer')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -297,45 +298,45 @@ class BaseDeviceCSVForm(NetBoxModelCSVForm):
|
||||
device_role = CSVModelChoiceField(
|
||||
queryset=DeviceRole.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Assigned role'
|
||||
help_text=_('Assigned role')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
manufacturer = CSVModelChoiceField(
|
||||
queryset=Manufacturer.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Device type manufacturer'
|
||||
help_text=_('Device type manufacturer')
|
||||
)
|
||||
device_type = CSVModelChoiceField(
|
||||
queryset=DeviceType.objects.all(),
|
||||
to_field_name='model',
|
||||
help_text='Device type model'
|
||||
help_text=_('Device type model')
|
||||
)
|
||||
platform = CSVModelChoiceField(
|
||||
queryset=Platform.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned platform'
|
||||
help_text=_('Assigned platform')
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=DeviceStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
virtual_chassis = CSVModelChoiceField(
|
||||
queryset=VirtualChassis.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Virtual chassis'
|
||||
help_text=_('Virtual chassis')
|
||||
)
|
||||
cluster = CSVModelChoiceField(
|
||||
queryset=Cluster.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Virtualization cluster'
|
||||
help_text=_('Virtualization cluster')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -360,29 +361,29 @@ class DeviceCSVForm(BaseDeviceCSVForm):
|
||||
site = CSVModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Assigned site'
|
||||
help_text=_('Assigned site')
|
||||
)
|
||||
location = CSVModelChoiceField(
|
||||
queryset=Location.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text="Assigned location (if any)"
|
||||
help_text=_("Assigned location (if any)")
|
||||
)
|
||||
rack = CSVModelChoiceField(
|
||||
queryset=Rack.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text="Assigned rack (if any)"
|
||||
help_text=_("Assigned rack (if any)")
|
||||
)
|
||||
face = CSVChoiceField(
|
||||
choices=DeviceFaceChoices,
|
||||
required=False,
|
||||
help_text='Mounted rack face'
|
||||
help_text=_('Mounted rack face')
|
||||
)
|
||||
airflow = CSVChoiceField(
|
||||
choices=DeviceAirflowChoices,
|
||||
required=False,
|
||||
help_text='Airflow direction'
|
||||
help_text=_('Airflow direction')
|
||||
)
|
||||
|
||||
class Meta(BaseDeviceCSVForm.Meta):
|
||||
@ -442,12 +443,12 @@ class ChildDeviceCSVForm(BaseDeviceCSVForm):
|
||||
parent = CSVModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Parent device'
|
||||
help_text=_('Parent device')
|
||||
)
|
||||
device_bay = CSVModelChoiceField(
|
||||
queryset=DeviceBay.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Device bay in which this device is installed'
|
||||
help_text=_('Device bay in which this device is installed')
|
||||
)
|
||||
|
||||
class Meta(BaseDeviceCSVForm.Meta):
|
||||
@ -492,14 +493,14 @@ class ConsolePortCSVForm(NetBoxModelCSVForm):
|
||||
type = CSVChoiceField(
|
||||
choices=ConsolePortTypeChoices,
|
||||
required=False,
|
||||
help_text='Port type'
|
||||
help_text=_('Port type')
|
||||
)
|
||||
speed = CSVTypedChoiceField(
|
||||
choices=ConsolePortSpeedChoices,
|
||||
coerce=int,
|
||||
empty_value=None,
|
||||
required=False,
|
||||
help_text='Port speed in bps'
|
||||
help_text=_('Port speed in bps')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -515,14 +516,14 @@ class ConsoleServerPortCSVForm(NetBoxModelCSVForm):
|
||||
type = CSVChoiceField(
|
||||
choices=ConsolePortTypeChoices,
|
||||
required=False,
|
||||
help_text='Port type'
|
||||
help_text=_('Port type')
|
||||
)
|
||||
speed = CSVTypedChoiceField(
|
||||
choices=ConsolePortSpeedChoices,
|
||||
coerce=int,
|
||||
empty_value=None,
|
||||
required=False,
|
||||
help_text='Port speed in bps'
|
||||
help_text=_('Port speed in bps')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -538,7 +539,7 @@ class PowerPortCSVForm(NetBoxModelCSVForm):
|
||||
type = CSVChoiceField(
|
||||
choices=PowerPortTypeChoices,
|
||||
required=False,
|
||||
help_text='Port type'
|
||||
help_text=_('Port type')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -556,18 +557,18 @@ class PowerOutletCSVForm(NetBoxModelCSVForm):
|
||||
type = CSVChoiceField(
|
||||
choices=PowerOutletTypeChoices,
|
||||
required=False,
|
||||
help_text='Outlet type'
|
||||
help_text=_('Outlet type')
|
||||
)
|
||||
power_port = CSVModelChoiceField(
|
||||
queryset=PowerPort.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Local power port which feeds this outlet'
|
||||
help_text=_('Local power port which feeds this outlet')
|
||||
)
|
||||
feed_leg = CSVChoiceField(
|
||||
choices=PowerOutletFeedLegChoices,
|
||||
required=False,
|
||||
help_text='Electrical phase (for three-phase circuits)'
|
||||
help_text=_('Electrical phase (for three-phase circuits)')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -606,23 +607,23 @@ class InterfaceCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent interface'
|
||||
help_text=_('Parent interface')
|
||||
)
|
||||
bridge = CSVModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Bridged interface'
|
||||
help_text=_('Bridged interface')
|
||||
)
|
||||
lag = CSVModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent LAG interface'
|
||||
help_text=_('Parent LAG interface')
|
||||
)
|
||||
type = CSVChoiceField(
|
||||
choices=InterfaceTypeChoices,
|
||||
help_text='Physical medium'
|
||||
help_text=_('Physical medium')
|
||||
)
|
||||
duplex = CSVChoiceField(
|
||||
choices=InterfaceDuplexChoices,
|
||||
@ -631,28 +632,28 @@ class InterfaceCSVForm(NetBoxModelCSVForm):
|
||||
poe_mode = CSVChoiceField(
|
||||
choices=InterfacePoEModeChoices,
|
||||
required=False,
|
||||
help_text='PoE mode'
|
||||
help_text=_('PoE mode')
|
||||
)
|
||||
poe_type = CSVChoiceField(
|
||||
choices=InterfacePoETypeChoices,
|
||||
required=False,
|
||||
help_text='PoE type'
|
||||
help_text=_('PoE type')
|
||||
)
|
||||
mode = CSVChoiceField(
|
||||
choices=InterfaceModeChoices,
|
||||
required=False,
|
||||
help_text='IEEE 802.1Q operational mode (for L2 interfaces)'
|
||||
help_text=_('IEEE 802.1Q operational mode (for L2 interfaces)')
|
||||
)
|
||||
vrf = CSVModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
to_field_name='rd',
|
||||
help_text='Assigned VRF'
|
||||
help_text=_('Assigned VRF')
|
||||
)
|
||||
rf_role = CSVChoiceField(
|
||||
choices=WirelessRoleChoices,
|
||||
required=False,
|
||||
help_text='Wireless role (AP/station)'
|
||||
help_text=_('Wireless role (AP/station)')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -692,11 +693,11 @@ class FrontPortCSVForm(NetBoxModelCSVForm):
|
||||
rear_port = CSVModelChoiceField(
|
||||
queryset=RearPort.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Corresponding rear port'
|
||||
help_text=_('Corresponding rear port')
|
||||
)
|
||||
type = CSVChoiceField(
|
||||
choices=PortTypeChoices,
|
||||
help_text='Physical medium classification'
|
||||
help_text=_('Physical medium classification')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -706,7 +707,7 @@ class FrontPortCSVForm(NetBoxModelCSVForm):
|
||||
'description', 'tags'
|
||||
)
|
||||
help_texts = {
|
||||
'rear_port_position': 'Mapped position on corresponding rear port',
|
||||
'rear_port_position': _('Mapped position on corresponding rear port'),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -738,7 +739,7 @@ class RearPortCSVForm(NetBoxModelCSVForm):
|
||||
to_field_name='name'
|
||||
)
|
||||
type = CSVChoiceField(
|
||||
help_text='Physical medium classification',
|
||||
help_text=_('Physical medium classification'),
|
||||
choices=PortTypeChoices,
|
||||
)
|
||||
|
||||
@ -746,7 +747,7 @@ class RearPortCSVForm(NetBoxModelCSVForm):
|
||||
model = RearPort
|
||||
fields = ('device', 'name', 'label', 'type', 'color', 'mark_connected', 'positions', 'description', 'tags')
|
||||
help_texts = {
|
||||
'positions': 'Number of front ports which may be mapped'
|
||||
'positions': _('Number of front ports which may be mapped')
|
||||
}
|
||||
|
||||
|
||||
@ -770,9 +771,9 @@ class DeviceBayCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Child device installed within this bay',
|
||||
help_text=_('Child device installed within this bay'),
|
||||
error_messages={
|
||||
'invalid_choice': 'Child device not found.',
|
||||
'invalid_choice': _('Child device not found.'),
|
||||
}
|
||||
)
|
||||
|
||||
@ -826,7 +827,7 @@ class InventoryItemCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Parent inventory item'
|
||||
help_text=_('Parent inventory item')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -863,7 +864,7 @@ class InventoryItemRoleCSVForm(NetBoxModelCSVForm):
|
||||
model = InventoryItemRole
|
||||
fields = ('name', 'slug', 'color', 'description')
|
||||
help_texts = {
|
||||
'color': mark_safe('RGB color in hexadecimal (e.g. <code>00ff00</code>)'),
|
||||
'color': mark_safe(_('RGB color in hexadecimal (e.g. <code>00ff00</code>)')),
|
||||
}
|
||||
|
||||
|
||||
@ -876,53 +877,53 @@ class CableCSVForm(NetBoxModelCSVForm):
|
||||
side_a_device = CSVModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Side A device'
|
||||
help_text=_('Side A device')
|
||||
)
|
||||
side_a_type = CSVContentTypeField(
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=CABLE_TERMINATION_MODELS,
|
||||
help_text='Side A type'
|
||||
help_text=_('Side A type')
|
||||
)
|
||||
side_a_name = forms.CharField(
|
||||
help_text='Side A component name'
|
||||
help_text=_('Side A component name')
|
||||
)
|
||||
|
||||
# Termination B
|
||||
side_b_device = CSVModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Side B device'
|
||||
help_text=_('Side B device')
|
||||
)
|
||||
side_b_type = CSVContentTypeField(
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=CABLE_TERMINATION_MODELS,
|
||||
help_text='Side B type'
|
||||
help_text=_('Side B type')
|
||||
)
|
||||
side_b_name = forms.CharField(
|
||||
help_text='Side B component name'
|
||||
help_text=_('Side B component name')
|
||||
)
|
||||
|
||||
# Cable attributes
|
||||
status = CSVChoiceField(
|
||||
choices=LinkStatusChoices,
|
||||
required=False,
|
||||
help_text='Connection status'
|
||||
help_text=_('Connection status')
|
||||
)
|
||||
type = CSVChoiceField(
|
||||
choices=CableTypeChoices,
|
||||
required=False,
|
||||
help_text='Physical medium classification'
|
||||
help_text=_('Physical medium classification')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
length_unit = CSVChoiceField(
|
||||
choices=CableLengthUnitChoices,
|
||||
required=False,
|
||||
help_text='Length unit'
|
||||
help_text=_('Length unit')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -932,7 +933,7 @@ class CableCSVForm(NetBoxModelCSVForm):
|
||||
'status', 'tenant', 'label', 'color', 'length', 'length_unit', 'description', 'comments', 'tags',
|
||||
]
|
||||
help_texts = {
|
||||
'color': mark_safe('RGB color in hexadecimal (e.g. <code>00ff00</code>)'),
|
||||
'color': mark_safe(_('RGB color in hexadecimal (e.g. <code>00ff00</code>)')),
|
||||
}
|
||||
|
||||
def _clean_side(self, side):
|
||||
@ -981,7 +982,7 @@ class VirtualChassisCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Master device'
|
||||
help_text=_('Master device')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -997,7 +998,7 @@ class PowerPanelCSVForm(NetBoxModelCSVForm):
|
||||
site = CSVModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Name of parent site'
|
||||
help_text=_('Name of parent site')
|
||||
)
|
||||
location = CSVModelChoiceField(
|
||||
queryset=Location.objects.all(),
|
||||
@ -1023,40 +1024,40 @@ class PowerFeedCSVForm(NetBoxModelCSVForm):
|
||||
site = CSVModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Assigned site'
|
||||
help_text=_('Assigned site')
|
||||
)
|
||||
power_panel = CSVModelChoiceField(
|
||||
queryset=PowerPanel.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Upstream power panel'
|
||||
help_text=_('Upstream power panel')
|
||||
)
|
||||
location = CSVModelChoiceField(
|
||||
queryset=Location.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text="Rack's location (if any)"
|
||||
help_text=_("Rack's location (if any)")
|
||||
)
|
||||
rack = CSVModelChoiceField(
|
||||
queryset=Rack.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Rack'
|
||||
help_text=_('Rack')
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=PowerFeedStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
type = CSVChoiceField(
|
||||
choices=PowerFeedTypeChoices,
|
||||
help_text='Primary or redundant'
|
||||
help_text=_('Primary or redundant')
|
||||
)
|
||||
supply = CSVChoiceField(
|
||||
choices=PowerFeedSupplyChoices,
|
||||
help_text='Supply type (AC/DC)'
|
||||
help_text=_('Supply type (AC/DC)')
|
||||
)
|
||||
phase = CSVChoiceField(
|
||||
choices=PowerFeedPhaseChoices,
|
||||
help_text='Single or three-phase'
|
||||
help_text=_('Single or three-phase')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.choices import *
|
||||
from dcim.constants import *
|
||||
@ -12,13 +13,13 @@ class InterfaceCommonForm(forms.Form):
|
||||
mac_address = forms.CharField(
|
||||
empty_value=None,
|
||||
required=False,
|
||||
label='MAC address'
|
||||
label=_('MAC address')
|
||||
)
|
||||
mtu = forms.IntegerField(
|
||||
required=False,
|
||||
min_value=INTERFACE_MTU_MIN,
|
||||
max_value=INTERFACE_MTU_MAX,
|
||||
label='MTU'
|
||||
label=_('MTU')
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from circuits.models import Circuit, CircuitTermination, Provider
|
||||
from dcim.models import *
|
||||
@ -16,7 +17,7 @@ def get_cable_form(a_type, b_type):
|
||||
|
||||
attrs[f'termination_{cable_end}_region'] = DynamicModelChoiceField(
|
||||
queryset=Region.objects.all(),
|
||||
label='Region',
|
||||
label=_('Region'),
|
||||
required=False,
|
||||
initial_params={
|
||||
'sites': f'$termination_{cable_end}_site'
|
||||
@ -24,7 +25,7 @@ def get_cable_form(a_type, b_type):
|
||||
)
|
||||
attrs[f'termination_{cable_end}_sitegroup'] = DynamicModelChoiceField(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
label='Site group',
|
||||
label=_('Site group'),
|
||||
required=False,
|
||||
initial_params={
|
||||
'sites': f'$termination_{cable_end}_site'
|
||||
@ -32,7 +33,7 @@ def get_cable_form(a_type, b_type):
|
||||
)
|
||||
attrs[f'termination_{cable_end}_site'] = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
label=_('Site'),
|
||||
required=False,
|
||||
query_params={
|
||||
'region_id': f'$termination_{cable_end}_region',
|
||||
@ -41,7 +42,7 @@ def get_cable_form(a_type, b_type):
|
||||
)
|
||||
attrs[f'termination_{cable_end}_location'] = DynamicModelChoiceField(
|
||||
queryset=Location.objects.all(),
|
||||
label='Location',
|
||||
label=_('Location'),
|
||||
required=False,
|
||||
null_option='None',
|
||||
query_params={
|
||||
@ -54,7 +55,7 @@ def get_cable_form(a_type, b_type):
|
||||
|
||||
attrs[f'termination_{cable_end}_rack'] = DynamicModelChoiceField(
|
||||
queryset=Rack.objects.all(),
|
||||
label='Rack',
|
||||
label=_('Rack'),
|
||||
required=False,
|
||||
null_option='None',
|
||||
initial_params={
|
||||
@ -67,7 +68,7 @@ def get_cable_form(a_type, b_type):
|
||||
)
|
||||
attrs[f'termination_{cable_end}_device'] = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
label='Device',
|
||||
label=_('Device'),
|
||||
required=False,
|
||||
initial_params={
|
||||
f'{term_cls._meta.model_name}s__in': f'${cable_end}_terminations'
|
||||
@ -93,7 +94,7 @@ def get_cable_form(a_type, b_type):
|
||||
|
||||
attrs[f'termination_{cable_end}_powerpanel'] = DynamicModelChoiceField(
|
||||
queryset=PowerPanel.objects.all(),
|
||||
label='Power Panel',
|
||||
label=_('Power Panel'),
|
||||
required=False,
|
||||
initial_params={
|
||||
'powerfeeds__in': f'${cable_end}_terminations'
|
||||
@ -105,7 +106,7 @@ def get_cable_form(a_type, b_type):
|
||||
)
|
||||
attrs[f'{cable_end}_terminations'] = DynamicModelMultipleChoiceField(
|
||||
queryset=term_cls.objects.all(),
|
||||
label='Power Feed',
|
||||
label=_('Power Feed'),
|
||||
disabled_indicator='_occupied',
|
||||
query_params={
|
||||
'power_panel_id': f'$termination_{cable_end}_powerpanel',
|
||||
@ -117,7 +118,7 @@ def get_cable_form(a_type, b_type):
|
||||
|
||||
attrs[f'termination_{cable_end}_provider'] = DynamicModelChoiceField(
|
||||
queryset=Provider.objects.all(),
|
||||
label='Provider',
|
||||
label=_('Provider'),
|
||||
initial_params={
|
||||
'circuits': f'$termination_{cable_end}_circuit'
|
||||
},
|
||||
@ -125,7 +126,7 @@ def get_cable_form(a_type, b_type):
|
||||
)
|
||||
attrs[f'termination_{cable_end}_circuit'] = DynamicModelChoiceField(
|
||||
queryset=Circuit.objects.all(),
|
||||
label='Circuit',
|
||||
label=_('Circuit'),
|
||||
initial_params={
|
||||
'terminations__in': f'${cable_end}_terminations'
|
||||
},
|
||||
@ -136,7 +137,7 @@ def get_cable_form(a_type, b_type):
|
||||
)
|
||||
attrs[f'{cable_end}_terminations'] = DynamicModelMultipleChoiceField(
|
||||
queryset=term_cls.objects.all(),
|
||||
label='Side',
|
||||
label=_('Side'),
|
||||
disabled_indicator='_occupied',
|
||||
query_params={
|
||||
'circuit_id': f'$termination_{cable_end}_circuit',
|
||||
|
@ -1,7 +1,7 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import gettext as _
|
||||
from timezone_field import TimeZoneFormField
|
||||
|
||||
from dcim.choices import *
|
||||
@ -163,14 +163,14 @@ class SiteForm(TenancyForm, NetBoxModelForm):
|
||||
'time_zone': StaticSelect(),
|
||||
}
|
||||
help_texts = {
|
||||
'name': "Full name of the site",
|
||||
'facility': "Data center provider and facility (e.g. Equinix NY7)",
|
||||
'time_zone': "Local time zone",
|
||||
'description': "Short description (will appear in sites list)",
|
||||
'physical_address': "Physical location of the building (e.g. for GPS)",
|
||||
'shipping_address': "If different from the physical address",
|
||||
'latitude': "Latitude in decimal format (xx.yyyyyy)",
|
||||
'longitude': "Longitude in decimal format (xx.yyyyyy)"
|
||||
'name': _("Full name of the site"),
|
||||
'facility': _("Data center provider and facility (e.g. Equinix NY7)"),
|
||||
'time_zone': _("Local time zone"),
|
||||
'description': _("Short description (will appear in sites list)"),
|
||||
'physical_address': _("Physical location of the building (e.g. for GPS)"),
|
||||
'shipping_address': _("If different from the physical address"),
|
||||
'latitude': _("Latitude in decimal format (xx.yyyyyy)"),
|
||||
'longitude': _("Longitude in decimal format (xx.yyyyyy)")
|
||||
}
|
||||
|
||||
|
||||
@ -282,10 +282,10 @@ class RackForm(TenancyForm, NetBoxModelForm):
|
||||
'outer_unit', 'mounting_depth', 'weight', 'weight_unit', 'description', 'comments', 'tags',
|
||||
]
|
||||
help_texts = {
|
||||
'site': "The site at which the rack exists",
|
||||
'name': "Organizational rack name",
|
||||
'facility_id': "The unique rack ID assigned by the facility",
|
||||
'u_height': "Height in rack units",
|
||||
'site': _("The site at which the rack exists"),
|
||||
'name': _("Organizational rack name"),
|
||||
'facility_id': _("The unique rack ID assigned by the facility"),
|
||||
'u_height': _("Height in rack units"),
|
||||
}
|
||||
widgets = {
|
||||
'status': StaticSelect(),
|
||||
@ -335,7 +335,7 @@ class RackReservationForm(TenancyForm, NetBoxModelForm):
|
||||
)
|
||||
units = NumericArrayField(
|
||||
base_field=forms.IntegerField(),
|
||||
help_text="Comma-separated list of numeric unit IDs. A range may be specified using a hyphen."
|
||||
help_text=_("Comma-separated list of numeric unit IDs. A range may be specified using a hyphen.")
|
||||
)
|
||||
user = forms.ModelChoiceField(
|
||||
queryset=User.objects.order_by(
|
||||
@ -519,7 +519,7 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
|
||||
)
|
||||
position = forms.DecimalField(
|
||||
required=False,
|
||||
help_text="The lowest-numbered unit occupied by the device",
|
||||
help_text=_("The lowest-numbered unit occupied by the device"),
|
||||
widget=APISelect(
|
||||
api_url='/api/dcim/racks/{{rack}}/elevation/',
|
||||
attrs={
|
||||
@ -577,13 +577,13 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
|
||||
)
|
||||
vc_position = forms.IntegerField(
|
||||
required=False,
|
||||
label='Position',
|
||||
help_text="The position in the virtual chassis this device is identified by"
|
||||
label=_('Position'),
|
||||
help_text=_("The position in the virtual chassis this device is identified by")
|
||||
)
|
||||
vc_priority = forms.IntegerField(
|
||||
required=False,
|
||||
label='Priority',
|
||||
help_text="The priority of the device in the virtual chassis"
|
||||
label=_('Priority'),
|
||||
help_text=_("The priority of the device in the virtual chassis")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -595,10 +595,10 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
|
||||
'description', 'comments', 'tags', 'local_context_data'
|
||||
]
|
||||
help_texts = {
|
||||
'device_role': "The function this device serves",
|
||||
'serial': "Chassis serial number",
|
||||
'local_context_data': "Local config context data overwrites all source contexts in the final rendered "
|
||||
"config context",
|
||||
'device_role': _("The function this device serves"),
|
||||
'serial': _("Chassis serial number"),
|
||||
'local_context_data': _("Local config context data overwrites all source contexts in the final rendered "
|
||||
"config context"),
|
||||
}
|
||||
widgets = {
|
||||
'face': StaticSelect(),
|
||||
@ -695,13 +695,13 @@ class ModuleForm(NetBoxModelForm):
|
||||
replicate_components = forms.BooleanField(
|
||||
required=False,
|
||||
initial=True,
|
||||
help_text="Automatically populate components associated with this module type"
|
||||
help_text=_("Automatically populate components associated with this module type")
|
||||
)
|
||||
|
||||
adopt_components = forms.BooleanField(
|
||||
required=False,
|
||||
initial=False,
|
||||
help_text="Adopt already existing components"
|
||||
help_text=_("Adopt already existing components")
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
@ -1390,7 +1390,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
label='Parent interface',
|
||||
label=_('Parent interface'),
|
||||
query_params={
|
||||
'device_id': '$device',
|
||||
}
|
||||
@ -1398,7 +1398,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
bridge = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
label='Bridged interface',
|
||||
label=_('Bridged interface'),
|
||||
query_params={
|
||||
'device_id': '$device',
|
||||
}
|
||||
@ -1406,7 +1406,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
lag = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
label='LAG interface',
|
||||
label=_('LAG interface'),
|
||||
query_params={
|
||||
'device_id': '$device',
|
||||
'type': 'lag',
|
||||
@ -1415,12 +1415,12 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
wireless_lan_group = DynamicModelChoiceField(
|
||||
queryset=WirelessLANGroup.objects.all(),
|
||||
required=False,
|
||||
label='Wireless LAN group'
|
||||
label=_('Wireless LAN group')
|
||||
)
|
||||
wireless_lans = DynamicModelMultipleChoiceField(
|
||||
queryset=WirelessLAN.objects.all(),
|
||||
required=False,
|
||||
label='Wireless LANs',
|
||||
label=_('Wireless LANs'),
|
||||
query_params={
|
||||
'group_id': '$wireless_lan_group',
|
||||
}
|
||||
@ -1428,12 +1428,12 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
vlan_group = DynamicModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
label='VLAN group'
|
||||
label=_('VLAN group')
|
||||
)
|
||||
untagged_vlan = DynamicModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
label='Untagged VLAN',
|
||||
label=_('Untagged VLAN'),
|
||||
query_params={
|
||||
'group_id': '$vlan_group',
|
||||
'available_on_device': '$device',
|
||||
@ -1442,7 +1442,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
tagged_vlans = DynamicModelMultipleChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
label='Tagged VLANs',
|
||||
label=_('Tagged VLANs'),
|
||||
query_params={
|
||||
'group_id': '$vlan_group',
|
||||
'available_on_device': '$device',
|
||||
@ -1451,13 +1451,13 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
|
||||
wwn = forms.CharField(
|
||||
empty_value=None,
|
||||
required=False,
|
||||
label='WWN'
|
||||
label=_('WWN')
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
@ -1495,8 +1495,8 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
|
||||
}
|
||||
help_texts = {
|
||||
'mode': INTERFACE_MODE_HELP_TEXT,
|
||||
'rf_channel_frequency': "Populated by selected channel (if set)",
|
||||
'rf_channel_width': "Populated by selected channel (if set)",
|
||||
'rf_channel_frequency': _("Populated by selected channel (if set)"),
|
||||
'rf_channel_width': _("Populated by selected channel (if set)"),
|
||||
}
|
||||
|
||||
|
||||
@ -1570,8 +1570,8 @@ class DeviceBayForm(DeviceComponentForm):
|
||||
class PopulateDeviceBayForm(BootstrapMixin, forms.Form):
|
||||
installed_device = forms.ModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
label='Child Device',
|
||||
help_text="Child devices must first be created and assigned to the site/rack of the parent device.",
|
||||
label=_('Child Device'),
|
||||
help_text=_("Child devices must first be created and assigned to the site/rack of the parent device."),
|
||||
widget=StaticSelect(),
|
||||
)
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import *
|
||||
from netbox.forms import NetBoxModelForm
|
||||
@ -39,7 +40,7 @@ class ComponentCreateForm(forms.Form):
|
||||
name = ExpandableNameField()
|
||||
label = ExpandableNameField(
|
||||
required=False,
|
||||
help_text='Alphanumeric ranges are supported. (Must match the number of objects being created.)'
|
||||
help_text=_('Alphanumeric ranges are supported. (Must match the number of objects being created.)')
|
||||
)
|
||||
|
||||
# Identify the fields which support replication (i.e. ExpandableNameFields). This is referenced by
|
||||
@ -97,8 +98,8 @@ class InterfaceTemplateCreateForm(ComponentCreateForm, model_forms.InterfaceTemp
|
||||
class FrontPortTemplateCreateForm(ComponentCreateForm, model_forms.FrontPortTemplateForm):
|
||||
rear_port = forms.MultipleChoiceField(
|
||||
choices=[],
|
||||
label='Rear ports',
|
||||
help_text='Select one rear port assignment for each front port being created.',
|
||||
label=_('Rear ports'),
|
||||
help_text=_('Select one rear port assignment for each front port being created.'),
|
||||
)
|
||||
|
||||
# Override fieldsets from FrontPortTemplateForm to omit rear_port_position
|
||||
@ -166,9 +167,9 @@ class DeviceBayTemplateCreateForm(ComponentCreateForm, model_forms.DeviceBayTemp
|
||||
|
||||
class ModuleBayTemplateCreateForm(ComponentCreateForm, model_forms.ModuleBayTemplateForm):
|
||||
position = ExpandableNameField(
|
||||
label='Position',
|
||||
label=_('Position'),
|
||||
required=False,
|
||||
help_text='Alphanumeric ranges are supported. (Must match the number of objects being created.)'
|
||||
help_text=_('Alphanumeric ranges are supported. (Must match the number of objects being created.)')
|
||||
)
|
||||
replication_fields = ('name', 'label', 'position')
|
||||
|
||||
@ -226,8 +227,8 @@ class InterfaceCreateForm(ComponentCreateForm, model_forms.InterfaceForm):
|
||||
class FrontPortCreateForm(ComponentCreateForm, model_forms.FrontPortForm):
|
||||
rear_port = forms.MultipleChoiceField(
|
||||
choices=[],
|
||||
label='Rear ports',
|
||||
help_text='Select one rear port assignment for each front port being created.',
|
||||
label=_('Rear ports'),
|
||||
help_text=_('Select one rear port assignment for each front port being created.'),
|
||||
)
|
||||
|
||||
# Override fieldsets from FrontPortForm to omit rear_port_position
|
||||
@ -290,9 +291,9 @@ class DeviceBayCreateForm(ComponentCreateForm, model_forms.DeviceBayForm):
|
||||
|
||||
class ModuleBayCreateForm(ComponentCreateForm, model_forms.ModuleBayForm):
|
||||
position = ExpandableNameField(
|
||||
label='Position',
|
||||
label=_('Position'),
|
||||
required=False,
|
||||
help_text='Alphanumeric ranges are supported. (Must match the number of objects being created.)'
|
||||
help_text=_('Alphanumeric ranges are supported. (Must match the number of objects being created.)')
|
||||
)
|
||||
replication_fields = ('name', 'label', 'position')
|
||||
|
||||
@ -352,7 +353,7 @@ class VirtualChassisCreateForm(NetBoxModelForm):
|
||||
initial_position = forms.IntegerField(
|
||||
initial=1,
|
||||
required=False,
|
||||
help_text='Position of the first member device. Increases by one for each additional member.'
|
||||
help_text=_('Position of the first member device. Increases by one for each additional member.')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.choices import InterfacePoEModeChoices, InterfacePoETypeChoices, InterfaceTypeChoices, PortTypeChoices
|
||||
from dcim.models import *
|
||||
@ -115,12 +116,12 @@ class InterfaceTemplateImportForm(ComponentTemplateImportForm):
|
||||
poe_mode = forms.ChoiceField(
|
||||
choices=InterfacePoEModeChoices,
|
||||
required=False,
|
||||
label='PoE mode'
|
||||
label=_('PoE mode')
|
||||
)
|
||||
poe_type = forms.ChoiceField(
|
||||
choices=InterfacePoETypeChoices,
|
||||
required=False,
|
||||
label='PoE type'
|
||||
label=_('PoE type')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -3,6 +3,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext as _
|
||||
from mptt.models import MPTTModel, TreeForeignKey
|
||||
|
||||
from dcim.choices import *
|
||||
@ -52,7 +53,7 @@ class ComponentTemplateModel(WebhooksMixin, ChangeLoggedModel):
|
||||
label = models.CharField(
|
||||
max_length=64,
|
||||
blank=True,
|
||||
help_text="Physical label"
|
||||
help_text=_("Physical label")
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
@ -222,13 +223,13 @@ class PowerPortTemplate(ModularComponentTemplateModel):
|
||||
blank=True,
|
||||
null=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum power draw (watts)"
|
||||
help_text=_("Maximum power draw (watts)")
|
||||
)
|
||||
allocated_draw = models.PositiveSmallIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Allocated power draw (watts)"
|
||||
help_text=_("Allocated power draw (watts)")
|
||||
)
|
||||
|
||||
component_model = PowerPort
|
||||
@ -283,7 +284,7 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
|
||||
max_length=50,
|
||||
choices=PowerOutletFeedLegChoices,
|
||||
blank=True,
|
||||
help_text="Phase (for three-phase feeds)"
|
||||
help_text=_("Phase (for three-phase feeds)")
|
||||
)
|
||||
|
||||
component_model = PowerOutlet
|
||||
@ -526,7 +527,7 @@ class ModuleBayTemplate(ComponentTemplateModel):
|
||||
position = models.CharField(
|
||||
max_length=30,
|
||||
blank=True,
|
||||
help_text='Identifier to reference when renaming installed components'
|
||||
help_text=_('Identifier to reference when renaming installed components')
|
||||
)
|
||||
|
||||
component_model = ModuleBay
|
||||
@ -621,7 +622,7 @@ class InventoryItemTemplate(MPTTModel, ComponentTemplateModel):
|
||||
max_length=50,
|
||||
verbose_name='Part ID',
|
||||
blank=True,
|
||||
help_text='Manufacturer-assigned part identifier'
|
||||
help_text=_('Manufacturer-assigned part identifier')
|
||||
)
|
||||
|
||||
objects = TreeManager()
|
||||
|
@ -7,6 +7,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.db.models import Sum
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from mptt.models import MPTTModel, TreeForeignKey
|
||||
|
||||
from dcim.choices import *
|
||||
@ -60,7 +61,7 @@ class ComponentModel(NetBoxModel):
|
||||
label = models.CharField(
|
||||
max_length=64,
|
||||
blank=True,
|
||||
help_text="Physical label"
|
||||
help_text=_("Physical label")
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
@ -129,7 +130,7 @@ class CabledObjectModel(models.Model):
|
||||
)
|
||||
mark_connected = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Treat as if a cable is connected"
|
||||
help_text=_("Treat as if a cable is connected")
|
||||
)
|
||||
|
||||
cable_terminations = GenericRelation(
|
||||
@ -261,13 +262,13 @@ class ConsolePort(ModularComponentModel, CabledObjectModel, PathEndpoint):
|
||||
max_length=50,
|
||||
choices=ConsolePortTypeChoices,
|
||||
blank=True,
|
||||
help_text='Physical port type'
|
||||
help_text=_('Physical port type')
|
||||
)
|
||||
speed = models.PositiveIntegerField(
|
||||
choices=ConsolePortSpeedChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='Port speed in bits per second'
|
||||
help_text=_('Port speed in bits per second')
|
||||
)
|
||||
|
||||
clone_fields = ('device', 'module', 'type', 'speed')
|
||||
@ -284,13 +285,13 @@ class ConsoleServerPort(ModularComponentModel, CabledObjectModel, PathEndpoint):
|
||||
max_length=50,
|
||||
choices=ConsolePortTypeChoices,
|
||||
blank=True,
|
||||
help_text='Physical port type'
|
||||
help_text=_('Physical port type')
|
||||
)
|
||||
speed = models.PositiveIntegerField(
|
||||
choices=ConsolePortSpeedChoices,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='Port speed in bits per second'
|
||||
help_text=_('Port speed in bits per second')
|
||||
)
|
||||
|
||||
clone_fields = ('device', 'module', 'type', 'speed')
|
||||
@ -311,19 +312,19 @@ class PowerPort(ModularComponentModel, CabledObjectModel, PathEndpoint):
|
||||
max_length=50,
|
||||
choices=PowerPortTypeChoices,
|
||||
blank=True,
|
||||
help_text='Physical port type'
|
||||
help_text=_('Physical port type')
|
||||
)
|
||||
maximum_draw = models.PositiveSmallIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Maximum power draw (watts)"
|
||||
help_text=_("Maximum power draw (watts)")
|
||||
)
|
||||
allocated_draw = models.PositiveSmallIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text="Allocated power draw (watts)"
|
||||
help_text=_("Allocated power draw (watts)")
|
||||
)
|
||||
|
||||
clone_fields = ('device', 'module', 'maximum_draw', 'allocated_draw')
|
||||
@ -420,7 +421,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint):
|
||||
max_length=50,
|
||||
choices=PowerOutletTypeChoices,
|
||||
blank=True,
|
||||
help_text='Physical port type'
|
||||
help_text=_('Physical port type')
|
||||
)
|
||||
power_port = models.ForeignKey(
|
||||
to='dcim.PowerPort',
|
||||
@ -433,7 +434,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint):
|
||||
max_length=50,
|
||||
choices=PowerOutletFeedLegChoices,
|
||||
blank=True,
|
||||
help_text="Phase (for three-phase feeds)"
|
||||
help_text=_("Phase (for three-phase feeds)")
|
||||
)
|
||||
|
||||
clone_fields = ('device', 'module', 'type', 'power_port', 'feed_leg')
|
||||
@ -550,7 +551,7 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
|
||||
mgmt_only = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name='Management only',
|
||||
help_text='This interface is used only for out-of-band management'
|
||||
help_text=_('This interface is used only for out-of-band management')
|
||||
)
|
||||
speed = models.PositiveIntegerField(
|
||||
blank=True,
|
||||
@ -567,7 +568,7 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name='WWN',
|
||||
help_text='64-bit World Wide Name'
|
||||
help_text=_('64-bit World Wide Name')
|
||||
)
|
||||
rf_role = models.CharField(
|
||||
max_length=30,
|
||||
@ -970,7 +971,7 @@ class ModuleBay(ComponentModel):
|
||||
position = models.CharField(
|
||||
max_length=30,
|
||||
blank=True,
|
||||
help_text='Identifier to reference when renaming installed components'
|
||||
help_text=_('Identifier to reference when renaming installed components')
|
||||
)
|
||||
|
||||
clone_fields = ('device',)
|
||||
@ -1084,7 +1085,7 @@ class InventoryItem(MPTTModel, ComponentModel):
|
||||
max_length=50,
|
||||
verbose_name='Part ID',
|
||||
blank=True,
|
||||
help_text='Manufacturer-assigned part identifier'
|
||||
help_text=_('Manufacturer-assigned part identifier')
|
||||
)
|
||||
serial = models.CharField(
|
||||
max_length=50,
|
||||
@ -1097,11 +1098,11 @@ class InventoryItem(MPTTModel, ComponentModel):
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Asset tag',
|
||||
help_text='A unique tag used to identify this item'
|
||||
help_text=_('A unique tag used to identify this item')
|
||||
)
|
||||
discovered = models.BooleanField(
|
||||
default=False,
|
||||
help_text='This item was automatically discovered'
|
||||
help_text=_('This item was automatically discovered')
|
||||
)
|
||||
|
||||
objects = TreeManager()
|
||||
|
@ -12,6 +12,7 @@ from django.db.models import F, ProtectedError
|
||||
from django.db.models.functions import Lower
|
||||
from django.urls import reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.choices import *
|
||||
from dcim.constants import *
|
||||
@ -84,7 +85,7 @@ class DeviceType(PrimaryModel, WeightMixin):
|
||||
part_number = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
help_text='Discrete part number (optional)'
|
||||
help_text=_('Discrete part number (optional)')
|
||||
)
|
||||
u_height = models.DecimalField(
|
||||
max_digits=4,
|
||||
@ -95,15 +96,15 @@ class DeviceType(PrimaryModel, WeightMixin):
|
||||
is_full_depth = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name='Is full depth',
|
||||
help_text='Device consumes both front and rear rack faces'
|
||||
help_text=_('Device consumes both front and rear rack faces')
|
||||
)
|
||||
subdevice_role = models.CharField(
|
||||
max_length=50,
|
||||
choices=SubdeviceRoleChoices,
|
||||
blank=True,
|
||||
verbose_name='Parent/child status',
|
||||
help_text='Parent devices house child devices in device bays. Leave blank '
|
||||
'if this device type is neither a parent nor a child.'
|
||||
help_text=_('Parent devices house child devices in device bays. Leave blank '
|
||||
'if this device type is neither a parent nor a child.')
|
||||
)
|
||||
airflow = models.CharField(
|
||||
max_length=50,
|
||||
@ -314,7 +315,7 @@ class ModuleType(PrimaryModel, WeightMixin):
|
||||
part_number = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
help_text='Discrete part number (optional)'
|
||||
help_text=_('Discrete part number (optional)')
|
||||
)
|
||||
|
||||
# Generic relations
|
||||
@ -400,7 +401,7 @@ class DeviceRole(OrganizationalModel):
|
||||
vm_role = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name='VM Role',
|
||||
help_text='Virtual machines may be assigned to this role'
|
||||
help_text=_('Virtual machines may be assigned to this role')
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
@ -419,19 +420,19 @@ class Platform(OrganizationalModel):
|
||||
related_name='platforms',
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='Optionally limit this platform to devices of a certain manufacturer'
|
||||
help_text=_('Optionally limit this platform to devices of a certain manufacturer')
|
||||
)
|
||||
napalm_driver = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
verbose_name='NAPALM driver',
|
||||
help_text='The name of the NAPALM driver to use when interacting with devices'
|
||||
help_text=_('The name of the NAPALM driver to use when interacting with devices')
|
||||
)
|
||||
napalm_args = models.JSONField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='NAPALM arguments',
|
||||
help_text='Additional arguments to pass when initiating the NAPALM driver (JSON format)'
|
||||
help_text=_('Additional arguments to pass when initiating the NAPALM driver (JSON format)')
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
@ -496,7 +497,7 @@ class Device(PrimaryModel, ConfigContextModel):
|
||||
null=True,
|
||||
unique=True,
|
||||
verbose_name='Asset tag',
|
||||
help_text='A unique tag used to identify this device'
|
||||
help_text=_('A unique tag used to identify this device')
|
||||
)
|
||||
site = models.ForeignKey(
|
||||
to='dcim.Site',
|
||||
@ -524,7 +525,7 @@ class Device(PrimaryModel, ConfigContextModel):
|
||||
null=True,
|
||||
validators=[MinValueValidator(1), MaxValueValidator(99.5)],
|
||||
verbose_name='Position (U)',
|
||||
help_text='The lowest-numbered unit occupied by the device'
|
||||
help_text=_('The lowest-numbered unit occupied by the device')
|
||||
)
|
||||
face = models.CharField(
|
||||
max_length=50,
|
||||
@ -929,7 +930,7 @@ class Module(PrimaryModel, ConfigContextModel):
|
||||
null=True,
|
||||
unique=True,
|
||||
verbose_name='Asset tag',
|
||||
help_text='A unique tag used to identify this device'
|
||||
help_text=_('A unique tag used to identify this device')
|
||||
)
|
||||
|
||||
clone_fields = ('device', 'module_type')
|
||||
|
@ -4,6 +4,7 @@ from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.choices import *
|
||||
from netbox.config import ConfigItem
|
||||
@ -125,7 +126,7 @@ class PowerFeed(PrimaryModel, PathEndpoint, CabledObjectModel):
|
||||
max_utilization = models.PositiveSmallIntegerField(
|
||||
validators=[MinValueValidator(1), MaxValueValidator(100)],
|
||||
default=ConfigItem('POWERFEED_DEFAULT_MAX_UTILIZATION'),
|
||||
help_text="Maximum permissible draw (percentage)"
|
||||
help_text=_("Maximum permissible draw (percentage)")
|
||||
)
|
||||
available_power = models.PositiveIntegerField(
|
||||
default=0,
|
||||
|
@ -10,6 +10,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.db.models import Count
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.choices import *
|
||||
from dcim.constants import *
|
||||
@ -64,7 +65,7 @@ class Rack(PrimaryModel, WeightMixin):
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Facility ID',
|
||||
help_text='Locally-assigned identifier'
|
||||
help_text=_('Locally-assigned identifier')
|
||||
)
|
||||
site = models.ForeignKey(
|
||||
to='dcim.Site',
|
||||
@ -96,7 +97,7 @@ class Rack(PrimaryModel, WeightMixin):
|
||||
related_name='racks',
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='Functional role'
|
||||
help_text=_('Functional role')
|
||||
)
|
||||
serial = models.CharField(
|
||||
max_length=50,
|
||||
@ -109,7 +110,7 @@ class Rack(PrimaryModel, WeightMixin):
|
||||
null=True,
|
||||
unique=True,
|
||||
verbose_name='Asset tag',
|
||||
help_text='A unique tag used to identify this rack'
|
||||
help_text=_('A unique tag used to identify this rack')
|
||||
)
|
||||
type = models.CharField(
|
||||
choices=RackTypeChoices,
|
||||
@ -121,28 +122,28 @@ class Rack(PrimaryModel, WeightMixin):
|
||||
choices=RackWidthChoices,
|
||||
default=RackWidthChoices.WIDTH_19IN,
|
||||
verbose_name='Width',
|
||||
help_text='Rail-to-rail width'
|
||||
help_text=_('Rail-to-rail width')
|
||||
)
|
||||
u_height = models.PositiveSmallIntegerField(
|
||||
default=RACK_U_HEIGHT_DEFAULT,
|
||||
verbose_name='Height (U)',
|
||||
validators=[MinValueValidator(1), MaxValueValidator(100)],
|
||||
help_text='Height in rack units'
|
||||
help_text=_('Height in rack units')
|
||||
)
|
||||
desc_units = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name='Descending units',
|
||||
help_text='Units are numbered top-to-bottom'
|
||||
help_text=_('Units are numbered top-to-bottom')
|
||||
)
|
||||
outer_width = models.PositiveSmallIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='Outer dimension of rack (width)'
|
||||
help_text=_('Outer dimension of rack (width)')
|
||||
)
|
||||
outer_depth = models.PositiveSmallIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='Outer dimension of rack (depth)'
|
||||
help_text=_('Outer dimension of rack (depth)')
|
||||
)
|
||||
outer_unit = models.CharField(
|
||||
max_length=50,
|
||||
@ -153,8 +154,8 @@ class Rack(PrimaryModel, WeightMixin):
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text=(
|
||||
'Maximum depth of a mounted device, in millimeters. For four-post racks, this is the '
|
||||
'distance between the front and rear rails.'
|
||||
_('Maximum depth of a mounted device, in millimeters. For four-post racks, this is the '
|
||||
'distance between the front and rear rails.')
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -2,6 +2,7 @@ from django.contrib.contenttypes.fields import GenericRelation
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from timezone_field import TimeZoneField
|
||||
|
||||
from dcim.choices import *
|
||||
@ -178,7 +179,7 @@ class Site(PrimaryModel):
|
||||
facility = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
help_text='Local facility ID or description'
|
||||
help_text=_('Local facility ID or description')
|
||||
)
|
||||
asns = models.ManyToManyField(
|
||||
to='ipam.ASN',
|
||||
@ -201,14 +202,14 @@ class Site(PrimaryModel):
|
||||
decimal_places=6,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='GPS coordinate (latitude)'
|
||||
help_text=_('GPS coordinate (latitude)')
|
||||
)
|
||||
longitude = models.DecimalField(
|
||||
max_digits=9,
|
||||
decimal_places=6,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='GPS coordinate (longitude)'
|
||||
help_text=_('GPS coordinate (longitude)')
|
||||
)
|
||||
|
||||
# Generic relations
|
||||
|
@ -2,6 +2,7 @@ import django_filters
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
||||
from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet
|
||||
@ -32,7 +33,7 @@ __all__ = (
|
||||
class WebhookFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
content_type_id = MultiValueNumberFilter(
|
||||
field_name='content_types__id'
|
||||
@ -61,7 +62,7 @@ class WebhookFilterSet(BaseFilterSet):
|
||||
class CustomFieldFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
type = django_filters.MultipleChoiceFilter(
|
||||
choices=CustomFieldTypeChoices
|
||||
@ -92,7 +93,7 @@ class CustomFieldFilterSet(BaseFilterSet):
|
||||
class CustomLinkFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
content_type_id = MultiValueNumberFilter(
|
||||
field_name='content_types__id'
|
||||
@ -119,7 +120,7 @@ class CustomLinkFilterSet(BaseFilterSet):
|
||||
class ExportTemplateFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
content_type_id = MultiValueNumberFilter(
|
||||
field_name='content_types__id'
|
||||
@ -142,7 +143,7 @@ class ExportTemplateFilterSet(BaseFilterSet):
|
||||
class SavedFilterFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
content_type_id = MultiValueNumberFilter(
|
||||
field_name='content_types__id'
|
||||
@ -150,13 +151,13 @@ class SavedFilterFilterSet(BaseFilterSet):
|
||||
content_types = ContentTypeFilter()
|
||||
user_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=User.objects.all(),
|
||||
label='User (ID)',
|
||||
label=_('User (ID)'),
|
||||
)
|
||||
user = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='user__username',
|
||||
queryset=User.objects.all(),
|
||||
to_field_name='username',
|
||||
label='User (name)',
|
||||
label=_('User (name)'),
|
||||
)
|
||||
usable = django_filters.BooleanFilter(
|
||||
method='_usable'
|
||||
@ -191,7 +192,7 @@ class SavedFilterFilterSet(BaseFilterSet):
|
||||
class ImageAttachmentFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
created = django_filters.DateTimeFilter()
|
||||
content_type = ContentTypeFilter()
|
||||
@ -211,13 +212,13 @@ class JournalEntryFilterSet(NetBoxModelFilterSet):
|
||||
assigned_object_type = ContentTypeFilter()
|
||||
created_by_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=User.objects.all(),
|
||||
label='User (ID)',
|
||||
label=_('User (ID)'),
|
||||
)
|
||||
created_by = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='created_by__username',
|
||||
queryset=User.objects.all(),
|
||||
to_field_name='username',
|
||||
label='User (name)',
|
||||
label=_('User (name)'),
|
||||
)
|
||||
kind = django_filters.MultipleChoiceFilter(
|
||||
choices=JournalEntryKindChoices
|
||||
@ -236,7 +237,7 @@ class JournalEntryFilterSet(NetBoxModelFilterSet):
|
||||
class TagFilterSet(ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
content_type = MultiValueCharFilter(
|
||||
method='_content_type'
|
||||
@ -288,138 +289,138 @@ class TagFilterSet(ChangeLoggedModelFilterSet):
|
||||
class ConfigContextFilterSet(ChangeLoggedModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
region_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='regions',
|
||||
queryset=Region.objects.all(),
|
||||
label='Region',
|
||||
label=_('Region'),
|
||||
)
|
||||
region = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='regions__slug',
|
||||
queryset=Region.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Region (slug)',
|
||||
label=_('Region (slug)'),
|
||||
)
|
||||
site_group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='site_groups__slug',
|
||||
queryset=SiteGroup.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site group (slug)',
|
||||
label=_('Site group (slug)'),
|
||||
)
|
||||
site_group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='site_groups',
|
||||
queryset=SiteGroup.objects.all(),
|
||||
label='Site group',
|
||||
label=_('Site group'),
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='sites',
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
label=_('Site'),
|
||||
)
|
||||
site = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='sites__slug',
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
location_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='locations',
|
||||
queryset=Location.objects.all(),
|
||||
label='Location',
|
||||
label=_('Location'),
|
||||
)
|
||||
location = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='locations__slug',
|
||||
queryset=Location.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Location (slug)',
|
||||
label=_('Location (slug)'),
|
||||
)
|
||||
device_type_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='device_types',
|
||||
queryset=DeviceType.objects.all(),
|
||||
label='Device type',
|
||||
label=_('Device type'),
|
||||
)
|
||||
role_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='roles',
|
||||
queryset=DeviceRole.objects.all(),
|
||||
label='Role',
|
||||
label=_('Role'),
|
||||
)
|
||||
role = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='roles__slug',
|
||||
queryset=DeviceRole.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Role (slug)',
|
||||
label=_('Role (slug)'),
|
||||
)
|
||||
platform_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='platforms',
|
||||
queryset=Platform.objects.all(),
|
||||
label='Platform',
|
||||
label=_('Platform'),
|
||||
)
|
||||
platform = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='platforms__slug',
|
||||
queryset=Platform.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Platform (slug)',
|
||||
label=_('Platform (slug)'),
|
||||
)
|
||||
cluster_type_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='cluster_types',
|
||||
queryset=ClusterType.objects.all(),
|
||||
label='Cluster type',
|
||||
label=_('Cluster type'),
|
||||
)
|
||||
cluster_type = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='cluster_types__slug',
|
||||
queryset=ClusterType.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Cluster type (slug)',
|
||||
label=_('Cluster type (slug)'),
|
||||
)
|
||||
cluster_group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='cluster_groups',
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
label='Cluster group',
|
||||
label=_('Cluster group'),
|
||||
)
|
||||
cluster_group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='cluster_groups__slug',
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Cluster group (slug)',
|
||||
label=_('Cluster group (slug)'),
|
||||
)
|
||||
cluster_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='clusters',
|
||||
queryset=Cluster.objects.all(),
|
||||
label='Cluster',
|
||||
label=_('Cluster'),
|
||||
)
|
||||
tenant_group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='tenant_groups',
|
||||
queryset=TenantGroup.objects.all(),
|
||||
label='Tenant group',
|
||||
label=_('Tenant group'),
|
||||
)
|
||||
tenant_group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='tenant_groups__slug',
|
||||
queryset=TenantGroup.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Tenant group (slug)',
|
||||
label=_('Tenant group (slug)'),
|
||||
)
|
||||
tenant_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='tenants',
|
||||
queryset=Tenant.objects.all(),
|
||||
label='Tenant',
|
||||
label=_('Tenant'),
|
||||
)
|
||||
tenant = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='tenants__slug',
|
||||
queryset=Tenant.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Tenant (slug)',
|
||||
label=_('Tenant (slug)'),
|
||||
)
|
||||
tag_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='tags',
|
||||
queryset=Tag.objects.all(),
|
||||
label='Tag',
|
||||
label=_('Tag'),
|
||||
)
|
||||
tag = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='tags__slug',
|
||||
queryset=Tag.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Tag (slug)',
|
||||
label=_('Tag (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -443,7 +444,7 @@ class ConfigContextFilterSet(ChangeLoggedModelFilterSet):
|
||||
class LocalConfigContextFilterSet(django_filters.FilterSet):
|
||||
local_context_data = django_filters.BooleanFilter(
|
||||
method='_local_context_data',
|
||||
label='Has local config context data',
|
||||
label=_('Has local config context data'),
|
||||
)
|
||||
|
||||
def _local_context_data(self, queryset, name, value):
|
||||
@ -453,19 +454,19 @@ class LocalConfigContextFilterSet(django_filters.FilterSet):
|
||||
class ObjectChangeFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
time = django_filters.DateTimeFromToRangeFilter()
|
||||
changed_object_type = ContentTypeFilter()
|
||||
user_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=User.objects.all(),
|
||||
label='User (ID)',
|
||||
label=_('User (ID)'),
|
||||
)
|
||||
user = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='user__username',
|
||||
queryset=User.objects.all(),
|
||||
to_field_name='username',
|
||||
label='User name',
|
||||
label=_('User name'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -491,7 +492,7 @@ class ObjectChangeFilterSet(BaseFilterSet):
|
||||
class JobResultFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
created = django_filters.DateTimeFilter()
|
||||
created__before = django_filters.DateTimeFilter(
|
||||
@ -547,7 +548,7 @@ class JobResultFilterSet(BaseFilterSet):
|
||||
class ContentTypeFilterSet(django_filters.FilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from extras.choices import *
|
||||
from extras.models import *
|
||||
@ -37,7 +38,7 @@ class CustomFieldBulkEditForm(BulkEditForm):
|
||||
required=False
|
||||
)
|
||||
ui_visibility = forms.ChoiceField(
|
||||
label="UI visibility",
|
||||
label=_("UI visibility"),
|
||||
choices=add_blank_choice(CustomFieldVisibilityChoices),
|
||||
required=False,
|
||||
initial='',
|
||||
@ -143,23 +144,23 @@ class WebhookBulkEditForm(BulkEditForm):
|
||||
http_method = forms.ChoiceField(
|
||||
choices=add_blank_choice(WebhookHttpMethodChoices),
|
||||
required=False,
|
||||
label='HTTP method'
|
||||
label=_('HTTP method')
|
||||
)
|
||||
payload_url = forms.CharField(
|
||||
required=False,
|
||||
label='Payload URL'
|
||||
label=_('Payload URL')
|
||||
)
|
||||
ssl_verification = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect(),
|
||||
label='SSL verification'
|
||||
label=_('SSL verification')
|
||||
)
|
||||
secret = forms.CharField(
|
||||
required=False
|
||||
)
|
||||
ca_file_path = forms.CharField(
|
||||
required=False,
|
||||
label='CA file path'
|
||||
label=_('CA file path')
|
||||
)
|
||||
|
||||
nullable_fields = ('secret', 'conditions', 'ca_file_path')
|
||||
|
@ -2,6 +2,7 @@ from django import forms
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.postgres.forms import SimpleArrayField
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from extras.choices import CustomFieldVisibilityChoices, CustomFieldTypeChoices
|
||||
from extras.models import *
|
||||
@ -22,26 +23,26 @@ class CustomFieldCSVForm(CSVModelForm):
|
||||
content_types = CSVMultipleContentTypeField(
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=FeatureQuery('custom_fields'),
|
||||
help_text="One or more assigned object types"
|
||||
help_text=_("One or more assigned object types")
|
||||
)
|
||||
type = CSVChoiceField(
|
||||
choices=CustomFieldTypeChoices,
|
||||
help_text='Field data type (e.g. text, integer, etc.)'
|
||||
help_text=_('Field data type (e.g. text, integer, etc.)')
|
||||
)
|
||||
object_type = CSVContentTypeField(
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=FeatureQuery('custom_fields'),
|
||||
required=False,
|
||||
help_text="Object type (for object or multi-object fields)"
|
||||
help_text=_("Object type (for object or multi-object fields)")
|
||||
)
|
||||
choices = SimpleArrayField(
|
||||
base_field=forms.CharField(),
|
||||
required=False,
|
||||
help_text='Comma-separated list of field choices'
|
||||
help_text=_('Comma-separated list of field choices')
|
||||
)
|
||||
ui_visibility = CSVChoiceField(
|
||||
choices=CustomFieldVisibilityChoices,
|
||||
help_text='How the custom field is displayed in the user interface'
|
||||
help_text=_('How the custom field is displayed in the user interface')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -57,7 +58,7 @@ class CustomLinkCSVForm(CSVModelForm):
|
||||
content_types = CSVMultipleContentTypeField(
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=FeatureQuery('custom_links'),
|
||||
help_text="One or more assigned object types"
|
||||
help_text=_("One or more assigned object types")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -72,7 +73,7 @@ class ExportTemplateCSVForm(CSVModelForm):
|
||||
content_types = CSVMultipleContentTypeField(
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=FeatureQuery('export_templates'),
|
||||
help_text="One or more assigned object types"
|
||||
help_text=_("One or more assigned object types")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -85,7 +86,7 @@ class ExportTemplateCSVForm(CSVModelForm):
|
||||
class SavedFilterCSVForm(CSVModelForm):
|
||||
content_types = CSVMultipleContentTypeField(
|
||||
queryset=ContentType.objects.all(),
|
||||
help_text="One or more assigned object types"
|
||||
help_text=_("One or more assigned object types")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -99,7 +100,7 @@ class WebhookCSVForm(CSVModelForm):
|
||||
content_types = CSVMultipleContentTypeField(
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=FeatureQuery('webhooks'),
|
||||
help_text="One or more assigned object types"
|
||||
help_text=_("One or more assigned object types")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -118,5 +119,5 @@ class TagCSVForm(CSVModelForm):
|
||||
model = Tag
|
||||
fields = ('name', 'slug', 'color', 'description')
|
||||
help_texts = {
|
||||
'color': mark_safe('RGB color in hexadecimal (e.g. <code>00ff00</code>)'),
|
||||
'color': mark_safe(_('RGB color in hexadecimal (e.g. <code>00ff00</code>)')),
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm):
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=FeatureQuery('custom_fields'),
|
||||
required=False,
|
||||
label='Object type'
|
||||
label=_('Object type')
|
||||
)
|
||||
type = MultipleChoiceField(
|
||||
choices=CustomFieldTypeChoices,
|
||||
@ -209,7 +209,7 @@ class WebhookFilterForm(SavedFiltersMixin, FilterForm):
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=FeatureQuery('webhooks'),
|
||||
required=False,
|
||||
label='Object type'
|
||||
label=_('Object type')
|
||||
)
|
||||
http_method = MultipleChoiceField(
|
||||
choices=WebhookHttpMethodChoices,
|
||||
|
@ -1,5 +1,6 @@
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from extras.models import *
|
||||
from extras.choices import CustomFieldVisibilityChoices
|
||||
@ -66,7 +67,7 @@ class SavedFiltersMixin(forms.Form):
|
||||
filter = DynamicModelMultipleChoiceField(
|
||||
queryset=SavedFilter.objects.all(),
|
||||
required=False,
|
||||
label='Saved Filter',
|
||||
label=_('Saved Filter'),
|
||||
query_params={
|
||||
'usable': True,
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django import forms
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.http import QueryDict
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
||||
from extras.choices import *
|
||||
@ -31,14 +32,14 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm):
|
||||
content_types = ContentTypeMultipleChoiceField(
|
||||
queryset=ContentType.objects.all(),
|
||||
limit_choices_to=FeatureQuery('custom_fields'),
|
||||
label='Model(s)'
|
||||
label=_('Model(s)')
|
||||
)
|
||||
object_type = ContentTypeChoiceField(
|
||||
queryset=ContentType.objects.all(),
|
||||
# TODO: Come up with a canonical way to register suitable models
|
||||
limit_choices_to=FeatureQuery('webhooks'),
|
||||
required=False,
|
||||
help_text="Type of the related object (for object/multi-object fields only)"
|
||||
help_text=_("Type of the related object (for object/multi-object fields only)")
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
@ -54,8 +55,8 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm):
|
||||
model = CustomField
|
||||
fields = '__all__'
|
||||
help_texts = {
|
||||
'type': "The type of data stored in this field. For object/multi-object fields, select the related object "
|
||||
"type below."
|
||||
'type': _("The type of data stored in this field. For object/multi-object fields, select the related object "
|
||||
"type below.")
|
||||
}
|
||||
widgets = {
|
||||
'type': StaticSelect(),
|
||||
@ -84,9 +85,9 @@ class CustomLinkForm(BootstrapMixin, forms.ModelForm):
|
||||
'link_url': forms.Textarea(attrs={'class': 'font-monospace'}),
|
||||
}
|
||||
help_texts = {
|
||||
'link_text': 'Jinja2 template code for the link text. Reference the object as <code>{{ object }}</code>. '
|
||||
'Links which render as empty text will not be displayed.',
|
||||
'link_url': 'Jinja2 template code for the link URL. Reference the object as <code>{{ object }}</code>.',
|
||||
'link_text': _('Jinja2 template code for the link text. Reference the object as <code>{{ object }}</code>. '
|
||||
'Links which render as empty text will not be displayed.'),
|
||||
'link_url': _('Jinja2 template code for the link URL. Reference the object as <code>{{ object }}</code>.'),
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from utilities.forms import BootstrapMixin, DateTimePicker
|
||||
|
||||
@ -11,6 +12,6 @@ class ReportForm(BootstrapMixin, forms.Form):
|
||||
schedule_at = forms.DateTimeField(
|
||||
required=False,
|
||||
widget=DateTimePicker(),
|
||||
label="Schedule at",
|
||||
help_text="Schedule execution of report to a set time",
|
||||
label=_("Schedule at"),
|
||||
help_text=_("Schedule execution of report to a set time"),
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from utilities.forms import BootstrapMixin, DateTimePicker
|
||||
|
||||
@ -11,14 +12,14 @@ class ScriptForm(BootstrapMixin, forms.Form):
|
||||
_commit = forms.BooleanField(
|
||||
required=False,
|
||||
initial=True,
|
||||
label="Commit changes",
|
||||
help_text="Commit changes to the database (uncheck for a dry-run)"
|
||||
label=_("Commit changes"),
|
||||
help_text=_("Commit changes to the database (uncheck for a dry-run)")
|
||||
)
|
||||
_schedule_at = forms.DateTimeField(
|
||||
required=False,
|
||||
widget=DateTimePicker(),
|
||||
label="Schedule at",
|
||||
help_text="Schedule execution of script to a set time",
|
||||
label=_("Schedule at"),
|
||||
help_text=_("Schedule execution of script to a set time"),
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -11,6 +11,7 @@ from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from extras.choices import *
|
||||
from extras.utils import FeatureQuery
|
||||
@ -57,25 +58,25 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
|
||||
to=ContentType,
|
||||
related_name='custom_fields',
|
||||
limit_choices_to=FeatureQuery('custom_fields'),
|
||||
help_text='The object(s) to which this field applies.'
|
||||
help_text=_('The object(s) to which this field applies.')
|
||||
)
|
||||
type = models.CharField(
|
||||
max_length=50,
|
||||
choices=CustomFieldTypeChoices,
|
||||
default=CustomFieldTypeChoices.TYPE_TEXT,
|
||||
help_text='The type of data this custom field holds'
|
||||
help_text=_('The type of data this custom field holds')
|
||||
)
|
||||
object_type = models.ForeignKey(
|
||||
to=ContentType,
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='The type of NetBox object this field maps to (for object fields)'
|
||||
help_text=_('The type of NetBox object this field maps to (for object fields)')
|
||||
)
|
||||
name = models.CharField(
|
||||
max_length=50,
|
||||
unique=True,
|
||||
help_text='Internal field name',
|
||||
help_text=_('Internal field name'),
|
||||
validators=(
|
||||
RegexValidator(
|
||||
regex=r'^[a-z0-9_]+$',
|
||||
@ -87,13 +88,13 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
|
||||
label = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
help_text='Name of the field as displayed to users (if not provided, '
|
||||
'the field\'s name will be used)'
|
||||
help_text=_('Name of the field as displayed to users (if not provided, '
|
||||
'the field\'s name will be used)')
|
||||
)
|
||||
group_name = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
help_text="Custom fields within the same group will be displayed together"
|
||||
help_text=_("Custom fields within the same group will be displayed together")
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
@ -101,64 +102,64 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
|
||||
)
|
||||
required = models.BooleanField(
|
||||
default=False,
|
||||
help_text='If true, this field is required when creating new objects '
|
||||
'or editing an existing object.'
|
||||
help_text=_('If true, this field is required when creating new objects '
|
||||
'or editing an existing object.')
|
||||
)
|
||||
search_weight = models.PositiveSmallIntegerField(
|
||||
default=1000,
|
||||
help_text='Weighting for search. Lower values are considered more important. '
|
||||
'Fields with a search weight of zero will be ignored.'
|
||||
help_text=_('Weighting for search. Lower values are considered more important. '
|
||||
'Fields with a search weight of zero will be ignored.')
|
||||
)
|
||||
filter_logic = models.CharField(
|
||||
max_length=50,
|
||||
choices=CustomFieldFilterLogicChoices,
|
||||
default=CustomFieldFilterLogicChoices.FILTER_LOOSE,
|
||||
help_text='Loose matches any instance of a given string; exact '
|
||||
'matches the entire field.'
|
||||
help_text=_('Loose matches any instance of a given string; exact '
|
||||
'matches the entire field.')
|
||||
)
|
||||
default = models.JSONField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='Default value for the field (must be a JSON value). Encapsulate '
|
||||
'strings with double quotes (e.g. "Foo").'
|
||||
help_text=_('Default value for the field (must be a JSON value). Encapsulate '
|
||||
'strings with double quotes (e.g. "Foo").')
|
||||
)
|
||||
weight = models.PositiveSmallIntegerField(
|
||||
default=100,
|
||||
verbose_name='Display weight',
|
||||
help_text='Fields with higher weights appear lower in a form.'
|
||||
help_text=_('Fields with higher weights appear lower in a form.')
|
||||
)
|
||||
validation_minimum = models.IntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Minimum value',
|
||||
help_text='Minimum allowed value (for numeric fields)'
|
||||
help_text=_('Minimum allowed value (for numeric fields)')
|
||||
)
|
||||
validation_maximum = models.IntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Maximum value',
|
||||
help_text='Maximum allowed value (for numeric fields)'
|
||||
help_text=_('Maximum allowed value (for numeric fields)')
|
||||
)
|
||||
validation_regex = models.CharField(
|
||||
blank=True,
|
||||
validators=[validate_regex],
|
||||
max_length=500,
|
||||
verbose_name='Validation regex',
|
||||
help_text='Regular expression to enforce on text field values. Use ^ and $ to force matching of entire string. '
|
||||
'For example, <code>^[A-Z]{3}$</code> will limit values to exactly three uppercase letters.'
|
||||
help_text=_('Regular expression to enforce on text field values. Use ^ and $ to force matching of entire string. '
|
||||
'For example, <code>^[A-Z]{3}$</code> will limit values to exactly three uppercase letters.')
|
||||
)
|
||||
choices = ArrayField(
|
||||
base_field=models.CharField(max_length=100),
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='Comma-separated list of available choices (for selection fields)'
|
||||
help_text=_('Comma-separated list of available choices (for selection fields)')
|
||||
)
|
||||
ui_visibility = models.CharField(
|
||||
max_length=50,
|
||||
choices=CustomFieldVisibilityChoices,
|
||||
default=CustomFieldVisibilityChoices.VISIBILITY_READ_WRITE,
|
||||
verbose_name='UI visibility',
|
||||
help_text='Specifies the visibility of custom field in the UI'
|
||||
help_text=_('Specifies the visibility of custom field in the UI')
|
||||
)
|
||||
|
||||
objects = CustomFieldManager()
|
||||
|
@ -12,6 +12,7 @@ from django.http import HttpResponse, QueryDict
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.translation import gettext as _
|
||||
from rest_framework.utils.encoders import JSONEncoder
|
||||
import django_rq
|
||||
|
||||
@ -51,7 +52,7 @@ class Webhook(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
|
||||
related_name='webhooks',
|
||||
verbose_name='Object types',
|
||||
limit_choices_to=FeatureQuery('webhooks'),
|
||||
help_text="The object(s) to which this Webhook applies."
|
||||
help_text=_("The object(s) to which this Webhook applies.")
|
||||
)
|
||||
name = models.CharField(
|
||||
max_length=150,
|
||||
@ -59,21 +60,21 @@ class Webhook(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
|
||||
)
|
||||
type_create = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Call this webhook when a matching object is created."
|
||||
help_text=_("Call this webhook when a matching object is created.")
|
||||
)
|
||||
type_update = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Call this webhook when a matching object is updated."
|
||||
help_text=_("Call this webhook when a matching object is updated.")
|
||||
)
|
||||
type_delete = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Call this webhook when a matching object is deleted."
|
||||
help_text=_("Call this webhook when a matching object is deleted.")
|
||||
)
|
||||
payload_url = models.CharField(
|
||||
max_length=500,
|
||||
verbose_name='URL',
|
||||
help_text='This URL will be called using the HTTP method defined when the webhook is called. '
|
||||
'Jinja2 template processing is supported with the same context as the request body.'
|
||||
help_text=_('This URL will be called using the HTTP method defined when the webhook is called. '
|
||||
'Jinja2 template processing is supported with the same context as the request body.')
|
||||
)
|
||||
enabled = models.BooleanField(
|
||||
default=True
|
||||
@ -88,46 +89,46 @@ class Webhook(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
|
||||
max_length=100,
|
||||
default=HTTP_CONTENT_TYPE_JSON,
|
||||
verbose_name='HTTP content type',
|
||||
help_text='The complete list of official content types is available '
|
||||
'<a href="https://www.iana.org/assignments/media-types/media-types.xhtml">here</a>.'
|
||||
help_text=_('The complete list of official content types is available '
|
||||
'<a href="https://www.iana.org/assignments/media-types/media-types.xhtml">here</a>.')
|
||||
)
|
||||
additional_headers = models.TextField(
|
||||
blank=True,
|
||||
help_text="User-supplied HTTP headers to be sent with the request in addition to the HTTP content type. "
|
||||
"Headers should be defined in the format <code>Name: Value</code>. Jinja2 template processing is "
|
||||
"supported with the same context as the request body (below)."
|
||||
help_text=_("User-supplied HTTP headers to be sent with the request in addition to the HTTP content type. "
|
||||
"Headers should be defined in the format <code>Name: Value</code>. Jinja2 template processing is "
|
||||
"supported with the same context as the request body (below).")
|
||||
)
|
||||
body_template = models.TextField(
|
||||
blank=True,
|
||||
help_text='Jinja2 template for a custom request body. If blank, a JSON object representing the change will be '
|
||||
'included. Available context data includes: <code>event</code>, <code>model</code>, '
|
||||
'<code>timestamp</code>, <code>username</code>, <code>request_id</code>, and <code>data</code>.'
|
||||
help_text=_('Jinja2 template for a custom request body. If blank, a JSON object representing the change will be '
|
||||
'included. Available context data includes: <code>event</code>, <code>model</code>, '
|
||||
'<code>timestamp</code>, <code>username</code>, <code>request_id</code>, and <code>data</code>.')
|
||||
)
|
||||
secret = models.CharField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
help_text="When provided, the request will include a 'X-Hook-Signature' "
|
||||
"header containing a HMAC hex digest of the payload body using "
|
||||
"the secret as the key. The secret is not transmitted in "
|
||||
"the request."
|
||||
help_text=_("When provided, the request will include a 'X-Hook-Signature' "
|
||||
"header containing a HMAC hex digest of the payload body using "
|
||||
"the secret as the key. The secret is not transmitted in "
|
||||
"the request.")
|
||||
)
|
||||
conditions = models.JSONField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="A set of conditions which determine whether the webhook will be generated."
|
||||
help_text=_("A set of conditions which determine whether the webhook will be generated.")
|
||||
)
|
||||
ssl_verification = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name='SSL verification',
|
||||
help_text="Enable SSL certificate verification. Disable with caution!"
|
||||
help_text=_("Enable SSL certificate verification. Disable with caution!")
|
||||
)
|
||||
ca_file_path = models.CharField(
|
||||
max_length=4096,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name='CA File Path',
|
||||
help_text='The specific CA certificate file to use for SSL verification. '
|
||||
'Leave blank to use the system defaults.'
|
||||
help_text=_('The specific CA certificate file to use for SSL verification. '
|
||||
'Leave blank to use the system defaults.')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -201,7 +202,7 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogged
|
||||
content_types = models.ManyToManyField(
|
||||
to=ContentType,
|
||||
related_name='custom_links',
|
||||
help_text='The object type(s) to which this link applies.'
|
||||
help_text=_('The object type(s) to which this link applies.')
|
||||
)
|
||||
name = models.CharField(
|
||||
max_length=100,
|
||||
@ -211,11 +212,11 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogged
|
||||
default=True
|
||||
)
|
||||
link_text = models.TextField(
|
||||
help_text="Jinja2 template code for link text"
|
||||
help_text=_("Jinja2 template code for link text")
|
||||
)
|
||||
link_url = models.TextField(
|
||||
verbose_name='Link URL',
|
||||
help_text="Jinja2 template code for link URL"
|
||||
help_text=_("Jinja2 template code for link URL")
|
||||
)
|
||||
weight = models.PositiveSmallIntegerField(
|
||||
default=100
|
||||
@ -223,17 +224,17 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogged
|
||||
group_name = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
help_text="Links with the same group will appear as a dropdown menu"
|
||||
help_text=_("Links with the same group will appear as a dropdown menu")
|
||||
)
|
||||
button_class = models.CharField(
|
||||
max_length=30,
|
||||
choices=CustomLinkButtonClassChoices,
|
||||
default=CustomLinkButtonClassChoices.DEFAULT,
|
||||
help_text="The class of the first link in a group will be used for the dropdown button"
|
||||
help_text=_("The class of the first link in a group will be used for the dropdown button")
|
||||
)
|
||||
new_window = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Force link to open in a new window"
|
||||
help_text=_("Force link to open in a new window")
|
||||
)
|
||||
|
||||
clone_fields = (
|
||||
@ -272,7 +273,7 @@ class ExportTemplate(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
|
||||
content_types = models.ManyToManyField(
|
||||
to=ContentType,
|
||||
related_name='export_templates',
|
||||
help_text='The object type(s) to which this template applies.'
|
||||
help_text=_('The object type(s) to which this template applies.')
|
||||
)
|
||||
name = models.CharField(
|
||||
max_length=100
|
||||
@ -282,23 +283,23 @@ class ExportTemplate(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
|
||||
blank=True
|
||||
)
|
||||
template_code = models.TextField(
|
||||
help_text='Jinja2 template code. The list of objects being exported is passed as a context variable named '
|
||||
'<code>queryset</code>.'
|
||||
help_text=_('Jinja2 template code. The list of objects being exported is passed as a context variable named '
|
||||
'<code>queryset</code>.')
|
||||
)
|
||||
mime_type = models.CharField(
|
||||
max_length=50,
|
||||
blank=True,
|
||||
verbose_name='MIME type',
|
||||
help_text='Defaults to <code>text/plain</code>'
|
||||
help_text=_('Defaults to <code>text/plain</code>')
|
||||
)
|
||||
file_extension = models.CharField(
|
||||
max_length=15,
|
||||
blank=True,
|
||||
help_text='Extension to append to the rendered filename'
|
||||
help_text=_('Extension to append to the rendered filename')
|
||||
)
|
||||
as_attachment = models.BooleanField(
|
||||
default=True,
|
||||
help_text="Download file as attachment"
|
||||
help_text=_("Download file as attachment")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -358,7 +359,7 @@ class SavedFilter(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
|
||||
content_types = models.ManyToManyField(
|
||||
to=ContentType,
|
||||
related_name='saved_filters',
|
||||
help_text='The object type(s) to which this filter applies.'
|
||||
help_text=_('The object type(s) to which this filter applies.')
|
||||
)
|
||||
name = models.CharField(
|
||||
max_length=100,
|
||||
@ -553,7 +554,7 @@ class JobResult(models.Model):
|
||||
related_name='job_results',
|
||||
verbose_name='Object types',
|
||||
limit_choices_to=FeatureQuery('job_results'),
|
||||
help_text="The object type to which this job result applies",
|
||||
help_text=_("The object type to which this job result applies"),
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
created = models.DateTimeField(
|
||||
|
@ -1,3 +1,4 @@
|
||||
from django.utils.translation import gettext as _
|
||||
from extras.plugins import PluginMenu, PluginMenuButton, PluginMenuItem
|
||||
|
||||
|
||||
@ -25,7 +26,7 @@ items = (
|
||||
)
|
||||
|
||||
menu = PluginMenu(
|
||||
label='Dummy',
|
||||
label=_('Dummy'),
|
||||
groups=(('Group 1', items),),
|
||||
)
|
||||
menu_items = items
|
||||
|
@ -3,6 +3,7 @@ import netaddr
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
from netaddr.core import AddrFormatError
|
||||
|
||||
from dcim.models import Device, Interface, Region, Site, SiteGroup
|
||||
@ -41,24 +42,24 @@ class VRFFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
import_target_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='import_targets',
|
||||
queryset=RouteTarget.objects.all(),
|
||||
label='Import target',
|
||||
label=_('Import target'),
|
||||
)
|
||||
import_target = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='import_targets__name',
|
||||
queryset=RouteTarget.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Import target (name)',
|
||||
label=_('Import target (name)'),
|
||||
)
|
||||
export_target_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='export_targets',
|
||||
queryset=RouteTarget.objects.all(),
|
||||
label='Export target',
|
||||
label=_('Export target'),
|
||||
)
|
||||
export_target = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='export_targets__name',
|
||||
queryset=RouteTarget.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Export target (name)',
|
||||
label=_('Export target (name)'),
|
||||
)
|
||||
|
||||
def search(self, queryset, name, value):
|
||||
@ -79,24 +80,24 @@ class RouteTargetFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
importing_vrf_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='importing_vrfs',
|
||||
queryset=VRF.objects.all(),
|
||||
label='Importing VRF',
|
||||
label=_('Importing VRF'),
|
||||
)
|
||||
importing_vrf = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='importing_vrfs__rd',
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='rd',
|
||||
label='Import VRF (RD)',
|
||||
label=_('Import VRF (RD)'),
|
||||
)
|
||||
exporting_vrf_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='exporting_vrfs',
|
||||
queryset=VRF.objects.all(),
|
||||
label='Exporting VRF',
|
||||
label=_('Exporting VRF'),
|
||||
)
|
||||
exporting_vrf = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='exporting_vrfs__rd',
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='rd',
|
||||
label='Export VRF (RD)',
|
||||
label=_('Export VRF (RD)'),
|
||||
)
|
||||
|
||||
def search(self, queryset, name, value):
|
||||
@ -126,17 +127,17 @@ class AggregateFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
)
|
||||
prefix = django_filters.CharFilter(
|
||||
method='filter_prefix',
|
||||
label='Prefix',
|
||||
label=_('Prefix'),
|
||||
)
|
||||
rir_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=RIR.objects.all(),
|
||||
label='RIR (ID)',
|
||||
label=_('RIR (ID)'),
|
||||
)
|
||||
rir = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='rir__slug',
|
||||
queryset=RIR.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='RIR (slug)',
|
||||
label=_('RIR (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -169,24 +170,24 @@ class AggregateFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
class ASNFilterSet(OrganizationalModelFilterSet, TenancyFilterSet):
|
||||
rir_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=RIR.objects.all(),
|
||||
label='RIR (ID)',
|
||||
label=_('RIR (ID)'),
|
||||
)
|
||||
rir = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='rir__slug',
|
||||
queryset=RIR.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='RIR (slug)',
|
||||
label=_('RIR (slug)'),
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='sites',
|
||||
queryset=Site.objects.all(),
|
||||
label='Site (ID)',
|
||||
label=_('Site (ID)'),
|
||||
)
|
||||
site = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='sites__slug',
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -218,19 +219,19 @@ class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
)
|
||||
prefix = MultiValueCharFilter(
|
||||
method='filter_prefix',
|
||||
label='Prefix',
|
||||
label=_('Prefix'),
|
||||
)
|
||||
within = django_filters.CharFilter(
|
||||
method='search_within',
|
||||
label='Within prefix',
|
||||
label=_('Within prefix'),
|
||||
)
|
||||
within_include = django_filters.CharFilter(
|
||||
method='search_within_include',
|
||||
label='Within and including prefix',
|
||||
label=_('Within and including prefix'),
|
||||
)
|
||||
contains = django_filters.CharFilter(
|
||||
method='search_contains',
|
||||
label='Prefixes which contain this prefix or IP',
|
||||
label=_('Prefixes which contain this prefix or IP'),
|
||||
)
|
||||
depth = MultiValueNumberFilter(
|
||||
field_name='_depth'
|
||||
@ -252,78 +253,78 @@ class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
)
|
||||
vrf_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=VRF.objects.all(),
|
||||
label='VRF',
|
||||
label=_('VRF'),
|
||||
)
|
||||
vrf = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vrf__rd',
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='rd',
|
||||
label='VRF (RD)',
|
||||
label=_('VRF (RD)'),
|
||||
)
|
||||
present_in_vrf_id = django_filters.ModelChoiceFilter(
|
||||
queryset=VRF.objects.all(),
|
||||
method='filter_present_in_vrf',
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
present_in_vrf = django_filters.ModelChoiceFilter(
|
||||
queryset=VRF.objects.all(),
|
||||
method='filter_present_in_vrf',
|
||||
to_field_name='rd',
|
||||
label='VRF (RD)',
|
||||
label=_('VRF (RD)'),
|
||||
)
|
||||
region_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
lookup_expr='in',
|
||||
label='Region (ID)',
|
||||
label=_('Region (ID)'),
|
||||
)
|
||||
region = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Region (slug)',
|
||||
label=_('Region (slug)'),
|
||||
)
|
||||
site_group_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='site__group',
|
||||
lookup_expr='in',
|
||||
label='Site group (ID)',
|
||||
label=_('Site group (ID)'),
|
||||
)
|
||||
site_group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='site__group',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Site group (slug)',
|
||||
label=_('Site group (slug)'),
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site (ID)',
|
||||
label=_('Site (ID)'),
|
||||
)
|
||||
site = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='site__slug',
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
vlan_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=VLAN.objects.all(),
|
||||
label='VLAN (ID)',
|
||||
label=_('VLAN (ID)'),
|
||||
)
|
||||
vlan_vid = django_filters.NumberFilter(
|
||||
field_name='vlan__vid',
|
||||
label='VLAN number (1-4094)',
|
||||
label=_('VLAN number (1-4094)'),
|
||||
)
|
||||
role_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Role.objects.all(),
|
||||
label='Role (ID)',
|
||||
label=_('Role (ID)'),
|
||||
)
|
||||
role = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='role__slug',
|
||||
queryset=Role.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Role (slug)',
|
||||
label=_('Role (slug)'),
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=PrefixStatusChoices,
|
||||
@ -406,27 +407,27 @@ class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
||||
)
|
||||
contains = django_filters.CharFilter(
|
||||
method='search_contains',
|
||||
label='Ranges which contain this prefix or IP',
|
||||
label=_('Ranges which contain this prefix or IP'),
|
||||
)
|
||||
vrf_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=VRF.objects.all(),
|
||||
label='VRF',
|
||||
label=_('VRF'),
|
||||
)
|
||||
vrf = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vrf__rd',
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='rd',
|
||||
label='VRF (RD)',
|
||||
label=_('VRF (RD)'),
|
||||
)
|
||||
role_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Role.objects.all(),
|
||||
label='Role (ID)',
|
||||
label=_('Role (ID)'),
|
||||
)
|
||||
role = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='role__slug',
|
||||
queryset=Role.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Role (slug)',
|
||||
label=_('Role (slug)'),
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=IPRangeStatusChoices,
|
||||
@ -468,87 +469,87 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
)
|
||||
parent = MultiValueCharFilter(
|
||||
method='search_by_parent',
|
||||
label='Parent prefix',
|
||||
label=_('Parent prefix'),
|
||||
)
|
||||
address = MultiValueCharFilter(
|
||||
method='filter_address',
|
||||
label='Address',
|
||||
label=_('Address'),
|
||||
)
|
||||
mask_length = django_filters.NumberFilter(
|
||||
method='filter_mask_length',
|
||||
label='Mask length',
|
||||
label=_('Mask length'),
|
||||
)
|
||||
vrf_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=VRF.objects.all(),
|
||||
label='VRF',
|
||||
label=_('VRF'),
|
||||
)
|
||||
vrf = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vrf__rd',
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='rd',
|
||||
label='VRF (RD)',
|
||||
label=_('VRF (RD)'),
|
||||
)
|
||||
present_in_vrf_id = django_filters.ModelChoiceFilter(
|
||||
queryset=VRF.objects.all(),
|
||||
method='filter_present_in_vrf',
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
present_in_vrf = django_filters.ModelChoiceFilter(
|
||||
queryset=VRF.objects.all(),
|
||||
method='filter_present_in_vrf',
|
||||
to_field_name='rd',
|
||||
label='VRF (RD)',
|
||||
label=_('VRF (RD)'),
|
||||
)
|
||||
device = MultiValueCharFilter(
|
||||
method='filter_device',
|
||||
field_name='name',
|
||||
label='Device (name)',
|
||||
label=_('Device (name)'),
|
||||
)
|
||||
device_id = MultiValueNumberFilter(
|
||||
method='filter_device',
|
||||
field_name='pk',
|
||||
label='Device (ID)',
|
||||
label=_('Device (ID)'),
|
||||
)
|
||||
virtual_machine = MultiValueCharFilter(
|
||||
method='filter_virtual_machine',
|
||||
field_name='name',
|
||||
label='Virtual machine (name)',
|
||||
label=_('Virtual machine (name)'),
|
||||
)
|
||||
virtual_machine_id = MultiValueNumberFilter(
|
||||
method='filter_virtual_machine',
|
||||
field_name='pk',
|
||||
label='Virtual machine (ID)',
|
||||
label=_('Virtual machine (ID)'),
|
||||
)
|
||||
interface = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='interface__name',
|
||||
queryset=Interface.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Interface (name)',
|
||||
label=_('Interface (name)'),
|
||||
)
|
||||
interface_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='interface',
|
||||
queryset=Interface.objects.all(),
|
||||
label='Interface (ID)',
|
||||
label=_('Interface (ID)'),
|
||||
)
|
||||
vminterface = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vminterface__name',
|
||||
queryset=VMInterface.objects.all(),
|
||||
to_field_name='name',
|
||||
label='VM interface (name)',
|
||||
label=_('VM interface (name)'),
|
||||
)
|
||||
vminterface_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vminterface',
|
||||
queryset=VMInterface.objects.all(),
|
||||
label='VM interface (ID)',
|
||||
label=_('VM interface (ID)'),
|
||||
)
|
||||
fhrpgroup_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='fhrpgroup',
|
||||
queryset=FHRPGroup.objects.all(),
|
||||
label='FHRP group (ID)',
|
||||
label=_('FHRP group (ID)'),
|
||||
)
|
||||
assigned_to_interface = django_filters.BooleanFilter(
|
||||
method='_assigned_to_interface',
|
||||
label='Is assigned to an interface',
|
||||
label=_('Is assigned to an interface'),
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=IPAddressStatusChoices,
|
||||
@ -688,27 +689,27 @@ class FHRPGroupAssignmentFilterSet(ChangeLoggedModelFilterSet):
|
||||
interface_type = ContentTypeFilter()
|
||||
group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=FHRPGroup.objects.all(),
|
||||
label='Group (ID)',
|
||||
label=_('Group (ID)'),
|
||||
)
|
||||
device = MultiValueCharFilter(
|
||||
method='filter_device',
|
||||
field_name='name',
|
||||
label='Device (name)',
|
||||
label=_('Device (name)'),
|
||||
)
|
||||
device_id = MultiValueNumberFilter(
|
||||
method='filter_device',
|
||||
field_name='pk',
|
||||
label='Device (ID)',
|
||||
label=_('Device (ID)'),
|
||||
)
|
||||
virtual_machine = MultiValueCharFilter(
|
||||
method='filter_virtual_machine',
|
||||
field_name='name',
|
||||
label='Virtual machine (name)',
|
||||
label=_('Virtual machine (name)'),
|
||||
)
|
||||
virtual_machine_id = MultiValueNumberFilter(
|
||||
method='filter_virtual_machine',
|
||||
field_name='pk',
|
||||
label='Virtual machine (ID)',
|
||||
label=_('Virtual machine (ID)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -787,57 +788,57 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
lookup_expr='in',
|
||||
label='Region (ID)',
|
||||
label=_('Region (ID)'),
|
||||
)
|
||||
region = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Region (slug)',
|
||||
label=_('Region (slug)'),
|
||||
)
|
||||
site_group_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='site__group',
|
||||
lookup_expr='in',
|
||||
label='Site group (ID)',
|
||||
label=_('Site group (ID)'),
|
||||
)
|
||||
site_group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='site__group',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Site group (slug)',
|
||||
label=_('Site group (slug)'),
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site (ID)',
|
||||
label=_('Site (ID)'),
|
||||
)
|
||||
site = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='site__slug',
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
label='Group (ID)',
|
||||
label=_('Group (ID)'),
|
||||
)
|
||||
group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='group__slug',
|
||||
queryset=VLANGroup.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Group',
|
||||
label=_('Group'),
|
||||
)
|
||||
role_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Role.objects.all(),
|
||||
label='Role (ID)',
|
||||
label=_('Role (ID)'),
|
||||
)
|
||||
role = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='role__slug',
|
||||
queryset=Role.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Role (slug)',
|
||||
label=_('Role (slug)'),
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=VLANStatusChoices,
|
||||
@ -893,23 +894,23 @@ class ServiceTemplateFilterSet(NetBoxModelFilterSet):
|
||||
class ServiceFilterSet(NetBoxModelFilterSet):
|
||||
device_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Device.objects.all(),
|
||||
label='Device (ID)',
|
||||
label=_('Device (ID)'),
|
||||
)
|
||||
device = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='device__name',
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Device (name)',
|
||||
label=_('Device (name)'),
|
||||
)
|
||||
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
label='Virtual machine (ID)',
|
||||
label=_('Virtual machine (ID)'),
|
||||
)
|
||||
virtual_machine = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_machine__name',
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Virtual machine (name)',
|
||||
label=_('Virtual machine (name)'),
|
||||
)
|
||||
port = NumericArrayFilter(
|
||||
field_name='ports',
|
||||
@ -939,24 +940,24 @@ class L2VPNFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
import_target_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='import_targets',
|
||||
queryset=RouteTarget.objects.all(),
|
||||
label='Import target',
|
||||
label=_('Import target'),
|
||||
)
|
||||
import_target = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='import_targets__name',
|
||||
queryset=RouteTarget.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Import target (name)',
|
||||
label=_('Import target (name)'),
|
||||
)
|
||||
export_target_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='export_targets',
|
||||
queryset=RouteTarget.objects.all(),
|
||||
label='Export target',
|
||||
label=_('Export target'),
|
||||
)
|
||||
export_target = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='export_targets__name',
|
||||
queryset=RouteTarget.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Export target (name)',
|
||||
label=_('Export target (name)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -977,92 +978,92 @@ class L2VPNFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
class L2VPNTerminationFilterSet(NetBoxModelFilterSet):
|
||||
l2vpn_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=L2VPN.objects.all(),
|
||||
label='L2VPN (ID)',
|
||||
label=_('L2VPN (ID)'),
|
||||
)
|
||||
l2vpn = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='l2vpn__slug',
|
||||
queryset=L2VPN.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='L2VPN (slug)',
|
||||
label=_('L2VPN (slug)'),
|
||||
)
|
||||
region = MultiValueCharFilter(
|
||||
method='filter_region',
|
||||
field_name='slug',
|
||||
label='Region (slug)',
|
||||
label=_('Region (slug)'),
|
||||
)
|
||||
region_id = MultiValueNumberFilter(
|
||||
method='filter_region',
|
||||
field_name='pk',
|
||||
label='Region (ID)',
|
||||
label=_('Region (ID)'),
|
||||
)
|
||||
site = MultiValueCharFilter(
|
||||
method='filter_site',
|
||||
field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
site_id = MultiValueNumberFilter(
|
||||
method='filter_site',
|
||||
field_name='pk',
|
||||
label='Site (ID)',
|
||||
label=_('Site (ID)'),
|
||||
)
|
||||
device = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='interface__device__name',
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Device (name)',
|
||||
label=_('Device (name)'),
|
||||
)
|
||||
device_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='interface__device',
|
||||
queryset=Device.objects.all(),
|
||||
label='Device (ID)',
|
||||
label=_('Device (ID)'),
|
||||
)
|
||||
virtual_machine = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vminterface__virtual_machine__name',
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Virtual machine (name)',
|
||||
label=_('Virtual machine (name)'),
|
||||
)
|
||||
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vminterface__virtual_machine',
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
label='Virtual machine (ID)',
|
||||
label=_('Virtual machine (ID)'),
|
||||
)
|
||||
interface = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='interface__name',
|
||||
queryset=Interface.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Interface (name)',
|
||||
label=_('Interface (name)'),
|
||||
)
|
||||
interface_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='interface',
|
||||
queryset=Interface.objects.all(),
|
||||
label='Interface (ID)',
|
||||
label=_('Interface (ID)'),
|
||||
)
|
||||
vminterface = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vminterface__name',
|
||||
queryset=VMInterface.objects.all(),
|
||||
to_field_name='name',
|
||||
label='VM interface (name)',
|
||||
label=_('VM interface (name)'),
|
||||
)
|
||||
vminterface_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vminterface',
|
||||
queryset=VMInterface.objects.all(),
|
||||
label='VM Interface (ID)',
|
||||
label=_('VM Interface (ID)'),
|
||||
)
|
||||
vlan = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vlan__name',
|
||||
queryset=VLAN.objects.all(),
|
||||
to_field_name='name',
|
||||
label='VLAN (name)',
|
||||
label=_('VLAN (name)'),
|
||||
)
|
||||
vlan_vid = django_filters.NumberFilter(
|
||||
field_name='vlan__vid',
|
||||
label='VLAN number (1-4094)',
|
||||
label=_('VLAN number (1-4094)'),
|
||||
)
|
||||
vlan_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vlan',
|
||||
queryset=VLAN.objects.all(),
|
||||
label='VLAN (ID)',
|
||||
label=_('VLAN (ID)'),
|
||||
)
|
||||
assigned_object_type = ContentTypeFilter()
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from utilities.forms import BootstrapMixin, ExpandableIPAddressField
|
||||
|
||||
@ -9,5 +10,5 @@ __all__ = (
|
||||
|
||||
class IPAddressBulkCreateForm(BootstrapMixin, forms.Form):
|
||||
pattern = ExpandableIPAddressField(
|
||||
label='Address pattern'
|
||||
label=_('Address pattern')
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import Region, Site, SiteGroup
|
||||
from ipam.choices import *
|
||||
@ -40,7 +41,7 @@ class VRFBulkEditForm(NetBoxModelBulkEditForm):
|
||||
enforce_unique = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect(),
|
||||
label='Enforce unique space'
|
||||
label=_('Enforce unique space')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -104,7 +105,7 @@ class ASNBulkEditForm(NetBoxModelBulkEditForm):
|
||||
rir = DynamicModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
required=False,
|
||||
label='RIR'
|
||||
label=_('RIR')
|
||||
)
|
||||
tenant = DynamicModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
@ -130,7 +131,7 @@ class AggregateBulkEditForm(NetBoxModelBulkEditForm):
|
||||
rir = DynamicModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
required=False,
|
||||
label='RIR'
|
||||
label=_('RIR')
|
||||
)
|
||||
tenant = DynamicModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
@ -191,7 +192,7 @@ class PrefixBulkEditForm(NetBoxModelBulkEditForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
prefix_length = forms.IntegerField(
|
||||
min_value=PREFIX_LENGTH_MIN,
|
||||
@ -214,12 +215,12 @@ class PrefixBulkEditForm(NetBoxModelBulkEditForm):
|
||||
is_pool = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect(),
|
||||
label='Is a pool'
|
||||
label=_('Is a pool')
|
||||
)
|
||||
mark_utilized = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=BulkEditNullBooleanSelect(),
|
||||
label='Treat as 100% utilized'
|
||||
label=_('Treat as 100% utilized')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -245,7 +246,7 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
tenant = DynamicModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
@ -282,7 +283,7 @@ class IPAddressBulkEditForm(NetBoxModelBulkEditForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
mask_length = forms.IntegerField(
|
||||
min_value=IPADDRESS_MASK_LENGTH_MIN,
|
||||
@ -306,7 +307,7 @@ class IPAddressBulkEditForm(NetBoxModelBulkEditForm):
|
||||
dns_name = forms.CharField(
|
||||
max_length=255,
|
||||
required=False,
|
||||
label='DNS name'
|
||||
label=_('DNS name')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -336,18 +337,18 @@ class FHRPGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
group_id = forms.IntegerField(
|
||||
min_value=0,
|
||||
required=False,
|
||||
label='Group ID'
|
||||
label=_('Group ID')
|
||||
)
|
||||
auth_type = forms.ChoiceField(
|
||||
choices=add_blank_choice(FHRPGroupAuthTypeChoices),
|
||||
required=False,
|
||||
widget=StaticSelect(),
|
||||
label='Authentication type'
|
||||
label=_('Authentication type')
|
||||
)
|
||||
auth_key = forms.CharField(
|
||||
max_length=255,
|
||||
required=False,
|
||||
label='Authentication key'
|
||||
label=_('Authentication key')
|
||||
)
|
||||
name = forms.CharField(
|
||||
max_length=100,
|
||||
@ -379,13 +380,13 @@ class VLANGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
min_value=VLAN_VID_MIN,
|
||||
max_value=VLAN_VID_MAX,
|
||||
required=False,
|
||||
label='Minimum child VLAN VID'
|
||||
label=_('Minimum child VLAN VID')
|
||||
)
|
||||
max_vid = forms.IntegerField(
|
||||
min_value=VLAN_VID_MIN,
|
||||
max_value=VLAN_VID_MAX,
|
||||
required=False,
|
||||
label='Maximum child VLAN VID'
|
||||
label=_('Maximum child VLAN VID')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django import forms
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import Device, Interface, Site
|
||||
from ipam.choices import *
|
||||
@ -36,7 +37,7 @@ class VRFCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -49,7 +50,7 @@ class RouteTargetCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -64,7 +65,7 @@ class RIRCSVForm(NetBoxModelCSVForm):
|
||||
model = RIR
|
||||
fields = ('name', 'slug', 'is_private', 'description', 'tags')
|
||||
help_texts = {
|
||||
'name': 'RIR name',
|
||||
'name': _('RIR name'),
|
||||
}
|
||||
|
||||
|
||||
@ -72,13 +73,13 @@ class AggregateCSVForm(NetBoxModelCSVForm):
|
||||
rir = CSVModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Assigned RIR'
|
||||
help_text=_('Assigned RIR')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -90,13 +91,13 @@ class ASNCSVForm(NetBoxModelCSVForm):
|
||||
rir = CSVModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Assigned RIR'
|
||||
help_text=_('Assigned RIR')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -117,41 +118,41 @@ class PrefixCSVForm(NetBoxModelCSVForm):
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned VRF'
|
||||
help_text=_('Assigned VRF')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
site = CSVModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned site'
|
||||
help_text=_('Assigned site')
|
||||
)
|
||||
vlan_group = CSVModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text="VLAN's group (if any)"
|
||||
help_text=_("VLAN's group (if any)")
|
||||
)
|
||||
vlan = CSVModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
to_field_name='vid',
|
||||
help_text="Assigned VLAN"
|
||||
help_text=_("Assigned VLAN")
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=PrefixStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
role = CSVModelChoiceField(
|
||||
queryset=Role.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Functional role'
|
||||
help_text=_('Functional role')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -181,23 +182,23 @@ class IPRangeCSVForm(NetBoxModelCSVForm):
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned VRF'
|
||||
help_text=_('Assigned VRF')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=IPRangeStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
role = CSVModelChoiceField(
|
||||
queryset=Role.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Functional role'
|
||||
help_text=_('Functional role')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -212,43 +213,43 @@ class IPAddressCSVForm(NetBoxModelCSVForm):
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned VRF'
|
||||
help_text=_('Assigned VRF')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=IPAddressStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
role = CSVChoiceField(
|
||||
choices=IPAddressRoleChoices,
|
||||
required=False,
|
||||
help_text='Functional role'
|
||||
help_text=_('Functional role')
|
||||
)
|
||||
device = CSVModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent device of assigned interface (if any)'
|
||||
help_text=_('Parent device of assigned interface (if any)')
|
||||
)
|
||||
virtual_machine = CSVModelChoiceField(
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent VM of assigned interface (if any)'
|
||||
help_text=_('Parent VM of assigned interface (if any)')
|
||||
)
|
||||
interface = CSVModelChoiceField(
|
||||
queryset=Interface.objects.none(), # Can also refer to VMInterface
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned interface'
|
||||
help_text=_('Assigned interface')
|
||||
)
|
||||
is_primary = forms.BooleanField(
|
||||
help_text='Make this the primary IP for the assigned device',
|
||||
help_text=_('Make this the primary IP for the assigned device'),
|
||||
required=False
|
||||
)
|
||||
|
||||
@ -333,7 +334,7 @@ class VLANGroupCSVForm(NetBoxModelCSVForm):
|
||||
scope_type = CSVContentTypeField(
|
||||
queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES),
|
||||
required=False,
|
||||
label='Scope type (app & model)'
|
||||
label=_('Scope type (app & model)')
|
||||
)
|
||||
min_vid = forms.IntegerField(
|
||||
min_value=VLAN_VID_MIN,
|
||||
@ -361,29 +362,29 @@ class VLANCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Site.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned site'
|
||||
help_text=_('Assigned site')
|
||||
)
|
||||
group = CSVModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned VLAN group'
|
||||
help_text=_('Assigned VLAN group')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=VLANStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
role = CSVModelChoiceField(
|
||||
queryset=Role.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Functional role'
|
||||
help_text=_('Functional role')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -398,7 +399,7 @@ class VLANCSVForm(NetBoxModelCSVForm):
|
||||
class ServiceTemplateCSVForm(NetBoxModelCSVForm):
|
||||
protocol = CSVChoiceField(
|
||||
choices=ServiceProtocolChoices,
|
||||
help_text='IP protocol'
|
||||
help_text=_('IP protocol')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -411,17 +412,17 @@ class ServiceCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Required if not assigned to a VM'
|
||||
help_text=_('Required if not assigned to a VM')
|
||||
)
|
||||
virtual_machine = CSVModelChoiceField(
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Required if not assigned to a device'
|
||||
help_text=_('Required if not assigned to a device')
|
||||
)
|
||||
protocol = CSVChoiceField(
|
||||
choices=ServiceProtocolChoices,
|
||||
help_text='IP protocol'
|
||||
help_text=_('IP protocol')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -437,7 +438,7 @@ class L2VPNCSVForm(NetBoxModelCSVForm):
|
||||
)
|
||||
type = CSVChoiceField(
|
||||
choices=L2VPNTypeChoices,
|
||||
help_text='L2VPN type'
|
||||
help_text=_('L2VPN type')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -450,31 +451,31 @@ class L2VPNTerminationCSVForm(NetBoxModelCSVForm):
|
||||
queryset=L2VPN.objects.all(),
|
||||
required=True,
|
||||
to_field_name='name',
|
||||
label='L2VPN',
|
||||
label=_('L2VPN'),
|
||||
)
|
||||
device = CSVModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent device (for interface)'
|
||||
help_text=_('Parent device (for interface)')
|
||||
)
|
||||
virtual_machine = CSVModelChoiceField(
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent virtual machine (for interface)'
|
||||
help_text=_('Parent virtual machine (for interface)')
|
||||
)
|
||||
interface = CSVModelChoiceField(
|
||||
queryset=Interface.objects.none(), # Can also refer to VMInterface
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned interface (device or VM)'
|
||||
help_text=_('Assigned interface (device or VM)')
|
||||
)
|
||||
vlan = CSVModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned VLAN'
|
||||
help_text=_('Assigned VLAN')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -397,13 +397,13 @@ class VLANGroupFilterForm(NetBoxModelFilterSetForm):
|
||||
required=False,
|
||||
min_value=VLAN_VID_MIN,
|
||||
max_value=VLAN_VID_MAX,
|
||||
label='Minimum VID'
|
||||
label=_('Minimum VID')
|
||||
)
|
||||
max_vid = forms.IntegerField(
|
||||
required=False,
|
||||
min_value=VLAN_VID_MIN,
|
||||
max_value=VLAN_VID_MAX,
|
||||
label='Maximum VID'
|
||||
label=_('Maximum VID')
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django import forms
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import Device, Interface, Location, Rack, Region, Site, SiteGroup
|
||||
from ipam.choices import *
|
||||
@ -67,7 +68,7 @@ class VRFForm(TenancyForm, NetBoxModelForm):
|
||||
'rd': "RD",
|
||||
}
|
||||
help_texts = {
|
||||
'rd': "Route distinguisher in any format",
|
||||
'rd': _("Route distinguisher in any format"),
|
||||
}
|
||||
|
||||
|
||||
@ -104,7 +105,7 @@ class RIRForm(NetBoxModelForm):
|
||||
class AggregateForm(TenancyForm, NetBoxModelForm):
|
||||
rir = DynamicModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
label='RIR'
|
||||
label=_('RIR')
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
@ -119,8 +120,8 @@ class AggregateForm(TenancyForm, NetBoxModelForm):
|
||||
'prefix', 'rir', 'date_added', 'tenant_group', 'tenant', 'description', 'comments', 'tags',
|
||||
]
|
||||
help_texts = {
|
||||
'prefix': "IPv4 or IPv6 network",
|
||||
'rir': "Regional Internet Registry responsible for this prefix",
|
||||
'prefix': _("IPv4 or IPv6 network"),
|
||||
'rir': _("Regional Internet Registry responsible for this prefix"),
|
||||
}
|
||||
widgets = {
|
||||
'date_added': DatePicker(),
|
||||
@ -130,11 +131,11 @@ class AggregateForm(TenancyForm, NetBoxModelForm):
|
||||
class ASNForm(TenancyForm, NetBoxModelForm):
|
||||
rir = DynamicModelChoiceField(
|
||||
queryset=RIR.objects.all(),
|
||||
label='RIR',
|
||||
label=_('RIR'),
|
||||
)
|
||||
sites = DynamicModelMultipleChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Sites',
|
||||
label=_('Sites'),
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
@ -150,8 +151,8 @@ class ASNForm(TenancyForm, NetBoxModelForm):
|
||||
'asn', 'rir', 'sites', 'tenant_group', 'tenant', 'description', 'comments', 'tags'
|
||||
]
|
||||
help_texts = {
|
||||
'asn': "AS number",
|
||||
'rir': "Regional Internet Registry responsible for this prefix",
|
||||
'asn': _("AS number"),
|
||||
'rir': _("Regional Internet Registry responsible for this prefix"),
|
||||
}
|
||||
widgets = {
|
||||
'date_added': DatePicker(),
|
||||
@ -189,7 +190,7 @@ class PrefixForm(TenancyForm, NetBoxModelForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
region = DynamicModelChoiceField(
|
||||
queryset=Region.objects.all(),
|
||||
@ -217,7 +218,7 @@ class PrefixForm(TenancyForm, NetBoxModelForm):
|
||||
vlan_group = DynamicModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
label='VLAN group',
|
||||
label=_('VLAN group'),
|
||||
null_option='None',
|
||||
query_params={
|
||||
'site': '$site'
|
||||
@ -229,7 +230,7 @@ class PrefixForm(TenancyForm, NetBoxModelForm):
|
||||
vlan = DynamicModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
label='VLAN',
|
||||
label=_('VLAN'),
|
||||
query_params={
|
||||
'site_id': '$site',
|
||||
'group_id': '$vlan_group',
|
||||
@ -262,7 +263,7 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
role = DynamicModelChoiceField(
|
||||
queryset=Role.objects.all(),
|
||||
@ -311,7 +312,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
vminterface = DynamicModelChoiceField(
|
||||
queryset=VMInterface.objects.all(),
|
||||
required=False,
|
||||
label='Interface',
|
||||
label=_('Interface'),
|
||||
query_params={
|
||||
'virtual_machine_id': '$virtual_machine'
|
||||
}
|
||||
@ -319,17 +320,17 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
fhrpgroup = DynamicModelChoiceField(
|
||||
queryset=FHRPGroup.objects.all(),
|
||||
required=False,
|
||||
label='FHRP Group'
|
||||
label=_('FHRP Group')
|
||||
)
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
nat_region = DynamicModelChoiceField(
|
||||
queryset=Region.objects.all(),
|
||||
required=False,
|
||||
label='Region',
|
||||
label=_('Region'),
|
||||
initial_params={
|
||||
'sites': '$nat_site'
|
||||
}
|
||||
@ -337,7 +338,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
nat_site_group = DynamicModelChoiceField(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
required=False,
|
||||
label='Site group',
|
||||
label=_('Site group'),
|
||||
initial_params={
|
||||
'sites': '$nat_site'
|
||||
}
|
||||
@ -345,7 +346,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
nat_site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False,
|
||||
label='Site',
|
||||
label=_('Site'),
|
||||
query_params={
|
||||
'region_id': '$nat_region',
|
||||
'group_id': '$nat_site_group',
|
||||
@ -354,7 +355,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
nat_rack = DynamicModelChoiceField(
|
||||
queryset=Rack.objects.all(),
|
||||
required=False,
|
||||
label='Rack',
|
||||
label=_('Rack'),
|
||||
null_option='None',
|
||||
query_params={
|
||||
'site_id': '$site'
|
||||
@ -363,7 +364,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
nat_device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
label='Device',
|
||||
label=_('Device'),
|
||||
query_params={
|
||||
'site_id': '$site',
|
||||
'rack_id': '$nat_rack',
|
||||
@ -372,12 +373,12 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
nat_cluster = DynamicModelChoiceField(
|
||||
queryset=Cluster.objects.all(),
|
||||
required=False,
|
||||
label='Cluster'
|
||||
label=_('Cluster')
|
||||
)
|
||||
nat_virtual_machine = DynamicModelChoiceField(
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
required=False,
|
||||
label='Virtual Machine',
|
||||
label=_('Virtual Machine'),
|
||||
query_params={
|
||||
'cluster_id': '$nat_cluster',
|
||||
}
|
||||
@ -385,12 +386,12 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
nat_vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
nat_inside = DynamicModelChoiceField(
|
||||
queryset=IPAddress.objects.all(),
|
||||
required=False,
|
||||
label='IP Address',
|
||||
label=_('IP Address'),
|
||||
query_params={
|
||||
'device_id': '$nat_device',
|
||||
'virtual_machine_id': '$nat_virtual_machine',
|
||||
@ -399,7 +400,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
|
||||
)
|
||||
primary_for_parent = forms.BooleanField(
|
||||
required=False,
|
||||
label='Make this the primary IP for the device/VM'
|
||||
label=_('Make this the primary IP for the device/VM')
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
@ -500,7 +501,7 @@ class IPAddressBulkAddForm(TenancyForm, NetBoxModelForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -518,11 +519,11 @@ class IPAddressAssignForm(BootstrapMixin, forms.Form):
|
||||
vrf_id = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
q = forms.CharField(
|
||||
required=False,
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
|
||||
|
||||
@ -532,16 +533,16 @@ class FHRPGroupForm(NetBoxModelForm):
|
||||
ip_vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
ip_address = IPNetworkFormField(
|
||||
required=False,
|
||||
label='Address'
|
||||
label=_('Address')
|
||||
)
|
||||
ip_status = forms.ChoiceField(
|
||||
choices=add_blank_choice(IPAddressStatusChoices),
|
||||
required=False,
|
||||
label='Status'
|
||||
label=_('Status')
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
@ -633,7 +634,7 @@ class VLANGroupForm(NetBoxModelForm):
|
||||
initial_params={
|
||||
'sites': '$site'
|
||||
},
|
||||
label='Site group'
|
||||
label=_('Site group')
|
||||
)
|
||||
site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
@ -670,7 +671,7 @@ class VLANGroupForm(NetBoxModelForm):
|
||||
initial_params={
|
||||
'clusters': '$cluster'
|
||||
},
|
||||
label='Cluster group'
|
||||
label=_('Cluster group')
|
||||
)
|
||||
cluster = DynamicModelChoiceField(
|
||||
queryset=Cluster.objects.all(),
|
||||
@ -734,7 +735,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
|
||||
),
|
||||
required=False,
|
||||
widget=StaticSelect,
|
||||
label='Group scope'
|
||||
label=_('Group scope')
|
||||
)
|
||||
group = DynamicModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
@ -742,7 +743,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
|
||||
query_params={
|
||||
'scope_type': '$scope_type',
|
||||
},
|
||||
label='VLAN Group'
|
||||
label=_('VLAN Group')
|
||||
)
|
||||
|
||||
# Site assignment fields
|
||||
@ -752,7 +753,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
|
||||
initial_params={
|
||||
'sites': '$site'
|
||||
},
|
||||
label='Region'
|
||||
label=_('Region')
|
||||
)
|
||||
sitegroup = DynamicModelChoiceField(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
@ -760,7 +761,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
|
||||
initial_params={
|
||||
'sites': '$site'
|
||||
},
|
||||
label='Site group'
|
||||
label=_('Site group')
|
||||
)
|
||||
site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
@ -786,12 +787,12 @@ class VLANForm(TenancyForm, NetBoxModelForm):
|
||||
'tags',
|
||||
]
|
||||
help_texts = {
|
||||
'site': "Leave blank if this VLAN spans multiple sites",
|
||||
'group': "VLAN group (optional)",
|
||||
'vid': "Configured VLAN ID",
|
||||
'name': "Configured VLAN name",
|
||||
'status': "Operational status of this VLAN",
|
||||
'role': "The primary function of this VLAN",
|
||||
'site': _("Leave blank if this VLAN spans multiple sites"),
|
||||
'group': _("VLAN group (optional)"),
|
||||
'vid': _("Configured VLAN ID"),
|
||||
'name': _("Configured VLAN name"),
|
||||
'status': _("Operational status of this VLAN"),
|
||||
'role': _("The primary function of this VLAN"),
|
||||
}
|
||||
widgets = {
|
||||
'status': StaticSelect(),
|
||||
@ -804,7 +805,7 @@ class ServiceTemplateForm(NetBoxModelForm):
|
||||
min_value=SERVICE_PORT_MIN,
|
||||
max_value=SERVICE_PORT_MAX
|
||||
),
|
||||
help_text="Comma-separated list of one or more port numbers. A range may be specified using a hyphen."
|
||||
help_text=_("Comma-separated list of one or more port numbers. A range may be specified using a hyphen.")
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
@ -836,12 +837,12 @@ class ServiceForm(NetBoxModelForm):
|
||||
min_value=SERVICE_PORT_MIN,
|
||||
max_value=SERVICE_PORT_MAX
|
||||
),
|
||||
help_text="Comma-separated list of one or more port numbers. A range may be specified using a hyphen."
|
||||
help_text=_("Comma-separated list of one or more port numbers. A range may be specified using a hyphen.")
|
||||
)
|
||||
ipaddresses = DynamicModelMultipleChoiceField(
|
||||
queryset=IPAddress.objects.all(),
|
||||
required=False,
|
||||
label='IP Addresses',
|
||||
label=_('IP Addresses'),
|
||||
query_params={
|
||||
'device_id': '$device',
|
||||
'virtual_machine_id': '$virtual_machine',
|
||||
@ -855,8 +856,8 @@ class ServiceForm(NetBoxModelForm):
|
||||
'device', 'virtual_machine', 'name', 'protocol', 'ports', 'ipaddresses', 'description', 'comments', 'tags',
|
||||
]
|
||||
help_texts = {
|
||||
'ipaddresses': "IP address assignment is optional. If no IPs are selected, the service is assumed to be "
|
||||
"reachable via all IPs assigned to the device.",
|
||||
'ipaddresses': _("IP address assignment is optional. If no IPs are selected, the service is assumed to be "
|
||||
"reachable via all IPs assigned to the device."),
|
||||
}
|
||||
widgets = {
|
||||
'protocol': StaticSelect(),
|
||||
@ -937,12 +938,12 @@ class L2VPNTerminationForm(NetBoxModelForm):
|
||||
queryset=L2VPN.objects.all(),
|
||||
required=True,
|
||||
query_params={},
|
||||
label='L2VPN',
|
||||
label=_('L2VPN'),
|
||||
fetch_trigger='open'
|
||||
)
|
||||
device_vlan = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
label="Available on Device",
|
||||
label=_("Available on Device"),
|
||||
required=False,
|
||||
query_params={}
|
||||
)
|
||||
@ -952,7 +953,7 @@ class L2VPNTerminationForm(NetBoxModelForm):
|
||||
query_params={
|
||||
'available_on_device': '$device_vlan'
|
||||
},
|
||||
label='VLAN'
|
||||
label=_('VLAN')
|
||||
)
|
||||
device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
@ -977,7 +978,7 @@ class L2VPNTerminationForm(NetBoxModelForm):
|
||||
query_params={
|
||||
'virtual_machine_id': '$virtual_machine'
|
||||
},
|
||||
label='Interface'
|
||||
label=_('Interface')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -6,6 +6,7 @@ from django.db import models
|
||||
from django.db.models import F
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.fields import ASNField
|
||||
from dcim.models import Device
|
||||
@ -64,7 +65,7 @@ class RIR(OrganizationalModel):
|
||||
is_private = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name='Private',
|
||||
help_text='IP space managed by this RIR is considered private'
|
||||
help_text=_('IP space managed by this RIR is considered private')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -84,7 +85,7 @@ class ASN(PrimaryModel):
|
||||
asn = ASNField(
|
||||
unique=True,
|
||||
verbose_name='ASN',
|
||||
help_text='32-bit autonomous system number'
|
||||
help_text=_('32-bit autonomous system number')
|
||||
)
|
||||
rir = models.ForeignKey(
|
||||
to='ipam.RIR',
|
||||
@ -263,7 +264,7 @@ class Prefix(GetAvailablePrefixesMixin, PrimaryModel):
|
||||
assigned to a VLAN where appropriate.
|
||||
"""
|
||||
prefix = IPNetworkField(
|
||||
help_text='IPv4 or IPv6 network with mask'
|
||||
help_text=_('IPv4 or IPv6 network with mask')
|
||||
)
|
||||
site = models.ForeignKey(
|
||||
to='dcim.Site',
|
||||
@ -300,7 +301,7 @@ class Prefix(GetAvailablePrefixesMixin, PrimaryModel):
|
||||
choices=PrefixStatusChoices,
|
||||
default=PrefixStatusChoices.STATUS_ACTIVE,
|
||||
verbose_name='Status',
|
||||
help_text='Operational status of this prefix'
|
||||
help_text=_('Operational status of this prefix')
|
||||
)
|
||||
role = models.ForeignKey(
|
||||
to='ipam.Role',
|
||||
@ -308,16 +309,16 @@ class Prefix(GetAvailablePrefixesMixin, PrimaryModel):
|
||||
related_name='prefixes',
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='The primary function of this prefix'
|
||||
help_text=_('The primary function of this prefix')
|
||||
)
|
||||
is_pool = models.BooleanField(
|
||||
verbose_name='Is a pool',
|
||||
default=False,
|
||||
help_text='All IP addresses within this prefix are considered usable'
|
||||
help_text=_('All IP addresses within this prefix are considered usable')
|
||||
)
|
||||
mark_utilized = models.BooleanField(
|
||||
default=False,
|
||||
help_text="Treat as 100% utilized"
|
||||
help_text=_("Treat as 100% utilized")
|
||||
)
|
||||
|
||||
# Cached depth & child counts
|
||||
@ -538,10 +539,10 @@ class IPRange(PrimaryModel):
|
||||
A range of IP addresses, defined by start and end addresses.
|
||||
"""
|
||||
start_address = IPAddressField(
|
||||
help_text='IPv4 or IPv6 address (with mask)'
|
||||
help_text=_('IPv4 or IPv6 address (with mask)')
|
||||
)
|
||||
end_address = IPAddressField(
|
||||
help_text='IPv4 or IPv6 address (with mask)'
|
||||
help_text=_('IPv4 or IPv6 address (with mask)')
|
||||
)
|
||||
size = models.PositiveIntegerField(
|
||||
editable=False
|
||||
@ -565,7 +566,7 @@ class IPRange(PrimaryModel):
|
||||
max_length=50,
|
||||
choices=IPRangeStatusChoices,
|
||||
default=IPRangeStatusChoices.STATUS_ACTIVE,
|
||||
help_text='Operational status of this range'
|
||||
help_text=_('Operational status of this range')
|
||||
)
|
||||
role = models.ForeignKey(
|
||||
to='ipam.Role',
|
||||
@ -573,7 +574,7 @@ class IPRange(PrimaryModel):
|
||||
related_name='ip_ranges',
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text='The primary function of this range'
|
||||
help_text=_('The primary function of this range')
|
||||
)
|
||||
|
||||
clone_fields = (
|
||||
@ -736,7 +737,7 @@ class IPAddress(PrimaryModel):
|
||||
which has a NAT outside IP, that Interface's Device can use either the inside or outside IP as its primary IP.
|
||||
"""
|
||||
address = IPAddressField(
|
||||
help_text='IPv4 or IPv6 address (with mask)'
|
||||
help_text=_('IPv4 or IPv6 address (with mask)')
|
||||
)
|
||||
vrf = models.ForeignKey(
|
||||
to='ipam.VRF',
|
||||
@ -757,13 +758,13 @@ class IPAddress(PrimaryModel):
|
||||
max_length=50,
|
||||
choices=IPAddressStatusChoices,
|
||||
default=IPAddressStatusChoices.STATUS_ACTIVE,
|
||||
help_text='The operational status of this IP'
|
||||
help_text=_('The operational status of this IP')
|
||||
)
|
||||
role = models.CharField(
|
||||
max_length=50,
|
||||
choices=IPAddressRoleChoices,
|
||||
blank=True,
|
||||
help_text='The functional role of this IP'
|
||||
help_text=_('The functional role of this IP')
|
||||
)
|
||||
assigned_object_type = models.ForeignKey(
|
||||
to=ContentType,
|
||||
@ -788,14 +789,14 @@ class IPAddress(PrimaryModel):
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='NAT (Inside)',
|
||||
help_text='The IP for which this address is the "outside" IP'
|
||||
help_text=_('The IP for which this address is the "outside" IP')
|
||||
)
|
||||
dns_name = models.CharField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
validators=[DNSValidator],
|
||||
verbose_name='DNS Name',
|
||||
help_text='Hostname or FQDN (not case-sensitive)'
|
||||
help_text=_('Hostname or FQDN (not case-sensitive)')
|
||||
)
|
||||
|
||||
objects = IPAddressManager()
|
||||
|
@ -4,6 +4,7 @@ from django.core.exceptions import ValidationError
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import Interface
|
||||
from ipam.choices import *
|
||||
@ -50,7 +51,7 @@ class VLANGroup(OrganizationalModel):
|
||||
MinValueValidator(VLAN_VID_MIN),
|
||||
MaxValueValidator(VLAN_VID_MAX)
|
||||
),
|
||||
help_text='Lowest permissible ID of a child VLAN'
|
||||
help_text=_('Lowest permissible ID of a child VLAN')
|
||||
)
|
||||
max_vid = models.PositiveSmallIntegerField(
|
||||
verbose_name='Maximum VLAN ID',
|
||||
@ -59,7 +60,7 @@ class VLANGroup(OrganizationalModel):
|
||||
MinValueValidator(VLAN_VID_MIN),
|
||||
MaxValueValidator(VLAN_VID_MAX)
|
||||
),
|
||||
help_text='Highest permissible ID of a child VLAN'
|
||||
help_text=_('Highest permissible ID of a child VLAN')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -1,5 +1,6 @@
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from ipam.constants import *
|
||||
from netbox.models import PrimaryModel
|
||||
@ -26,7 +27,7 @@ class VRF(PrimaryModel):
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Route distinguisher',
|
||||
help_text='Unique route distinguisher (as defined in RFC 4364)'
|
||||
help_text=_('Unique route distinguisher (as defined in RFC 4364)')
|
||||
)
|
||||
tenant = models.ForeignKey(
|
||||
to='tenancy.Tenant',
|
||||
@ -38,7 +39,7 @@ class VRF(PrimaryModel):
|
||||
enforce_unique = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name='Enforce unique space',
|
||||
help_text='Prevent duplicate prefixes/IP addresses within this VRF'
|
||||
help_text=_('Prevent duplicate prefixes/IP addresses within this VRF')
|
||||
)
|
||||
import_targets = models.ManyToManyField(
|
||||
to='ipam.RouteTarget',
|
||||
@ -76,7 +77,7 @@ class RouteTarget(PrimaryModel):
|
||||
name = models.CharField(
|
||||
max_length=VRF_RD_MAX_LENGTH, # Same format options as VRF RD (RFC 4360 section 4)
|
||||
unique=True,
|
||||
help_text='Route target value (formatted in accordance with RFC 4360)'
|
||||
help_text=_('Route target value (formatted in accordance with RFC 4360)')
|
||||
)
|
||||
tenant = models.ForeignKey(
|
||||
to='tenancy.Tenant',
|
||||
|
@ -1,5 +1,6 @@
|
||||
from django import forms
|
||||
from django.contrib.postgres.forms import SimpleArrayField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class ConfigParam:
|
||||
@ -18,9 +19,9 @@ PARAMS = (
|
||||
# Banners
|
||||
ConfigParam(
|
||||
name='BANNER_LOGIN',
|
||||
label='Login banner',
|
||||
label=_('Login banner'),
|
||||
default='',
|
||||
description="Additional content to display on the login page",
|
||||
description=_("Additional content to display on the login page"),
|
||||
field_kwargs={
|
||||
'widget': forms.Textarea(
|
||||
attrs={'class': 'vLargeTextField'}
|
||||
@ -29,9 +30,9 @@ PARAMS = (
|
||||
),
|
||||
ConfigParam(
|
||||
name='BANNER_TOP',
|
||||
label='Top banner',
|
||||
label=_('Top banner'),
|
||||
default='',
|
||||
description="Additional content to display at the top of every page",
|
||||
description=_("Additional content to display at the top of every page"),
|
||||
field_kwargs={
|
||||
'widget': forms.Textarea(
|
||||
attrs={'class': 'vLargeTextField'}
|
||||
@ -40,9 +41,9 @@ PARAMS = (
|
||||
),
|
||||
ConfigParam(
|
||||
name='BANNER_BOTTOM',
|
||||
label='Bottom banner',
|
||||
label=_('Bottom banner'),
|
||||
default='',
|
||||
description="Additional content to display at the bottom of every page",
|
||||
description=_("Additional content to display at the bottom of every page"),
|
||||
field_kwargs={
|
||||
'widget': forms.Textarea(
|
||||
attrs={'class': 'vLargeTextField'}
|
||||
@ -53,69 +54,69 @@ PARAMS = (
|
||||
# IPAM
|
||||
ConfigParam(
|
||||
name='ENFORCE_GLOBAL_UNIQUE',
|
||||
label='Globally unique IP space',
|
||||
label=_('Globally unique IP space'),
|
||||
default=False,
|
||||
description="Enforce unique IP addressing within the global table",
|
||||
description=_("Enforce unique IP addressing within the global table"),
|
||||
field=forms.BooleanField
|
||||
),
|
||||
ConfigParam(
|
||||
name='PREFER_IPV4',
|
||||
label='Prefer IPv4',
|
||||
label=_('Prefer IPv4'),
|
||||
default=False,
|
||||
description="Prefer IPv4 addresses over IPv6",
|
||||
description=_("Prefer IPv4 addresses over IPv6"),
|
||||
field=forms.BooleanField
|
||||
),
|
||||
|
||||
# Racks
|
||||
ConfigParam(
|
||||
name='RACK_ELEVATION_DEFAULT_UNIT_HEIGHT',
|
||||
label='Rack unit height',
|
||||
label=_('Rack unit height'),
|
||||
default=22,
|
||||
description="Default unit height for rendered rack elevations",
|
||||
description=_("Default unit height for rendered rack elevations"),
|
||||
field=forms.IntegerField
|
||||
),
|
||||
ConfigParam(
|
||||
name='RACK_ELEVATION_DEFAULT_UNIT_WIDTH',
|
||||
label='Rack unit width',
|
||||
label=_('Rack unit width'),
|
||||
default=220,
|
||||
description="Default unit width for rendered rack elevations",
|
||||
description=_("Default unit width for rendered rack elevations"),
|
||||
field=forms.IntegerField
|
||||
),
|
||||
|
||||
# Power
|
||||
ConfigParam(
|
||||
name='POWERFEED_DEFAULT_VOLTAGE',
|
||||
label='Powerfeed voltage',
|
||||
label=_('Powerfeed voltage'),
|
||||
default=120,
|
||||
description="Default voltage for powerfeeds",
|
||||
description=_("Default voltage for powerfeeds"),
|
||||
field=forms.IntegerField
|
||||
),
|
||||
|
||||
ConfigParam(
|
||||
name='POWERFEED_DEFAULT_AMPERAGE',
|
||||
label='Powerfeed amperage',
|
||||
label=_('Powerfeed amperage'),
|
||||
default=15,
|
||||
description="Default amperage for powerfeeds",
|
||||
description=_("Default amperage for powerfeeds"),
|
||||
field=forms.IntegerField
|
||||
),
|
||||
|
||||
ConfigParam(
|
||||
name='POWERFEED_DEFAULT_MAX_UTILIZATION',
|
||||
label='Powerfeed max utilization',
|
||||
label=_('Powerfeed max utilization'),
|
||||
default=80,
|
||||
description="Default max utilization for powerfeeds",
|
||||
description=_("Default max utilization for powerfeeds"),
|
||||
field=forms.IntegerField
|
||||
),
|
||||
|
||||
# Security
|
||||
ConfigParam(
|
||||
name='ALLOWED_URL_SCHEMES',
|
||||
label='Allowed URL schemes',
|
||||
label=_('Allowed URL schemes'),
|
||||
default=(
|
||||
'file', 'ftp', 'ftps', 'http', 'https', 'irc', 'mailto', 'sftp', 'ssh', 'tel', 'telnet', 'tftp', 'vnc',
|
||||
'xmpp',
|
||||
),
|
||||
description="Permitted schemes for URLs in user-provided content",
|
||||
description=_("Permitted schemes for URLs in user-provided content"),
|
||||
field=SimpleArrayField,
|
||||
field_kwargs={'base_field': forms.CharField()}
|
||||
),
|
||||
@ -123,13 +124,13 @@ PARAMS = (
|
||||
# Pagination
|
||||
ConfigParam(
|
||||
name='PAGINATE_COUNT',
|
||||
label='Default page size',
|
||||
label=_('Default page size'),
|
||||
default=50,
|
||||
field=forms.IntegerField
|
||||
),
|
||||
ConfigParam(
|
||||
name='MAX_PAGE_SIZE',
|
||||
label='Maximum page size',
|
||||
label=_('Maximum page size'),
|
||||
default=1000,
|
||||
field=forms.IntegerField
|
||||
),
|
||||
@ -137,9 +138,9 @@ PARAMS = (
|
||||
# Validation
|
||||
ConfigParam(
|
||||
name='CUSTOM_VALIDATORS',
|
||||
label='Custom validators',
|
||||
label=_('Custom validators'),
|
||||
default={},
|
||||
description="Custom validation rules (JSON)",
|
||||
description=_("Custom validation rules (JSON)"),
|
||||
field=forms.JSONField,
|
||||
field_kwargs={
|
||||
'widget': forms.Textarea(
|
||||
@ -151,28 +152,28 @@ PARAMS = (
|
||||
# NAPALM
|
||||
ConfigParam(
|
||||
name='NAPALM_USERNAME',
|
||||
label='NAPALM username',
|
||||
label=_('NAPALM username'),
|
||||
default='',
|
||||
description="Username to use when connecting to devices via NAPALM"
|
||||
description=_("Username to use when connecting to devices via NAPALM")
|
||||
),
|
||||
ConfigParam(
|
||||
name='NAPALM_PASSWORD',
|
||||
label='NAPALM password',
|
||||
label=_('NAPALM password'),
|
||||
default='',
|
||||
description="Password to use when connecting to devices via NAPALM"
|
||||
description=_("Password to use when connecting to devices via NAPALM")
|
||||
),
|
||||
ConfigParam(
|
||||
name='NAPALM_TIMEOUT',
|
||||
label='NAPALM timeout',
|
||||
label=_('NAPALM timeout'),
|
||||
default=30,
|
||||
description="NAPALM connection timeout (in seconds)",
|
||||
description=_("NAPALM connection timeout (in seconds)"),
|
||||
field=forms.IntegerField
|
||||
),
|
||||
ConfigParam(
|
||||
name='NAPALM_ARGS',
|
||||
label='NAPALM arguments',
|
||||
label=_('NAPALM arguments'),
|
||||
default={},
|
||||
description="Additional arguments to pass when invoking a NAPALM driver (as JSON data)",
|
||||
description=_("Additional arguments to pass when invoking a NAPALM driver (as JSON data)"),
|
||||
field=forms.JSONField,
|
||||
field_kwargs={
|
||||
'widget': forms.Textarea(
|
||||
@ -184,46 +185,46 @@ PARAMS = (
|
||||
# User preferences
|
||||
ConfigParam(
|
||||
name='DEFAULT_USER_PREFERENCES',
|
||||
label='Default preferences',
|
||||
label=_('Default preferences'),
|
||||
default={},
|
||||
description="Default preferences for new users",
|
||||
description=_("Default preferences for new users"),
|
||||
field=forms.JSONField
|
||||
),
|
||||
|
||||
# Miscellaneous
|
||||
ConfigParam(
|
||||
name='MAINTENANCE_MODE',
|
||||
label='Maintenance mode',
|
||||
label=_('Maintenance mode'),
|
||||
default=False,
|
||||
description="Enable maintenance mode",
|
||||
description=_("Enable maintenance mode"),
|
||||
field=forms.BooleanField
|
||||
),
|
||||
ConfigParam(
|
||||
name='GRAPHQL_ENABLED',
|
||||
label='GraphQL enabled',
|
||||
label=_('GraphQL enabled'),
|
||||
default=True,
|
||||
description="Enable the GraphQL API",
|
||||
description=_("Enable the GraphQL API"),
|
||||
field=forms.BooleanField
|
||||
),
|
||||
ConfigParam(
|
||||
name='CHANGELOG_RETENTION',
|
||||
label='Changelog retention',
|
||||
label=_('Changelog retention'),
|
||||
default=90,
|
||||
description="Days to retain changelog history (set to zero for unlimited)",
|
||||
description=_("Days to retain changelog history (set to zero for unlimited)"),
|
||||
field=forms.IntegerField
|
||||
),
|
||||
ConfigParam(
|
||||
name='JOBRESULT_RETENTION',
|
||||
label='Job result retention',
|
||||
label=_('Job result retention'),
|
||||
default=90,
|
||||
description="Days to retain job result history (set to zero for unlimited)",
|
||||
description=_("Days to retain job result history (set to zero for unlimited)"),
|
||||
field=forms.IntegerField
|
||||
),
|
||||
ConfigParam(
|
||||
name='MAPS_URL',
|
||||
label='Maps URL',
|
||||
label=_('Maps URL'),
|
||||
default='https://maps.google.com/?q=',
|
||||
description="Base URL for mapping geographic locations"
|
||||
description=_("Base URL for mapping geographic locations")
|
||||
),
|
||||
|
||||
)
|
||||
|
@ -5,6 +5,7 @@ from django.db import models
|
||||
from django_filters.exceptions import FieldLookupError
|
||||
from django_filters.utils import get_model_field, resolve_field
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from extras.choices import CustomFieldFilterLogicChoices
|
||||
from extras.filters import TagFilter
|
||||
@ -235,7 +236,7 @@ class NetBoxModelFilterSet(ChangeLoggedModelFilterSet):
|
||||
"""
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
tag = TagFilter()
|
||||
|
||||
|
@ -17,7 +17,7 @@ LOOKUP_CHOICES = (
|
||||
|
||||
class SearchForm(BootstrapMixin, forms.Form):
|
||||
q = forms.CharField(
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'hx-get': '',
|
||||
@ -29,7 +29,7 @@ class SearchForm(BootstrapMixin, forms.Form):
|
||||
obj_types = forms.MultipleChoiceField(
|
||||
choices=[],
|
||||
required=False,
|
||||
label='Object type(s)',
|
||||
label=_('Object type(s)'),
|
||||
widget=StaticSelectMultiple()
|
||||
)
|
||||
lookup = forms.ChoiceField(
|
||||
|
@ -2,6 +2,7 @@ from django import forms
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from extras.choices import CustomFieldFilterLogicChoices, CustomFieldTypeChoices, CustomFieldVisibilityChoices
|
||||
from extras.forms.mixins import CustomFieldsMixin, SavedFiltersMixin
|
||||
@ -132,7 +133,7 @@ class NetBoxModelFilterSetForm(BootstrapMixin, CustomFieldsMixin, SavedFiltersMi
|
||||
"""
|
||||
q = forms.CharField(
|
||||
required=False,
|
||||
label='Search'
|
||||
label=_('Search')
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -1,119 +1,120 @@
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from netbox.registry import registry
|
||||
from . import *
|
||||
|
||||
|
||||
#
|
||||
# Nav menus
|
||||
#
|
||||
|
||||
ORGANIZATION_MENU = Menu(
|
||||
label='Organization',
|
||||
label=_('Organization'),
|
||||
icon_class='mdi mdi-domain',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='Sites',
|
||||
label=_('Sites'),
|
||||
items=(
|
||||
get_model_item('dcim', 'site', 'Sites'),
|
||||
get_model_item('dcim', 'region', 'Regions'),
|
||||
get_model_item('dcim', 'sitegroup', 'Site Groups'),
|
||||
get_model_item('dcim', 'location', 'Locations'),
|
||||
get_model_item('dcim', 'site', _('Sites')),
|
||||
get_model_item('dcim', 'region', _('Regions')),
|
||||
get_model_item('dcim', 'sitegroup', _('Site Groups')),
|
||||
get_model_item('dcim', 'location', _('Locations')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Racks',
|
||||
label=_('Racks'),
|
||||
items=(
|
||||
get_model_item('dcim', 'rack', 'Racks'),
|
||||
get_model_item('dcim', 'rackrole', 'Rack Roles'),
|
||||
get_model_item('dcim', 'rackreservation', 'Reservations'),
|
||||
get_model_item('dcim', 'rack', _('Racks')),
|
||||
get_model_item('dcim', 'rackrole', _('Rack Roles')),
|
||||
get_model_item('dcim', 'rackreservation', _('Reservations')),
|
||||
MenuItem(
|
||||
link='dcim:rack_elevation_list',
|
||||
link_text='Elevations',
|
||||
link_text=_('Elevations'),
|
||||
permissions=['dcim.view_rack']
|
||||
),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Tenancy',
|
||||
label=_('Tenancy'),
|
||||
items=(
|
||||
get_model_item('tenancy', 'tenant', 'Tenants'),
|
||||
get_model_item('tenancy', 'tenantgroup', 'Tenant Groups'),
|
||||
get_model_item('tenancy', 'tenant', _('Tenants')),
|
||||
get_model_item('tenancy', 'tenantgroup', _('Tenant Groups')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Contacts',
|
||||
label=_('Contacts'),
|
||||
items=(
|
||||
get_model_item('tenancy', 'contact', 'Contacts'),
|
||||
get_model_item('tenancy', 'contactgroup', 'Contact Groups'),
|
||||
get_model_item('tenancy', 'contactrole', 'Contact Roles'),
|
||||
get_model_item('tenancy', 'contact', _('Contacts')),
|
||||
get_model_item('tenancy', 'contactgroup', _('Contact Groups')),
|
||||
get_model_item('tenancy', 'contactrole', _('Contact Roles')),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
DEVICES_MENU = Menu(
|
||||
label='Devices',
|
||||
label=_('Devices'),
|
||||
icon_class='mdi mdi-server',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='Devices',
|
||||
label=_('Devices'),
|
||||
items=(
|
||||
get_model_item('dcim', 'device', 'Devices'),
|
||||
get_model_item('dcim', 'module', 'Modules'),
|
||||
get_model_item('dcim', 'devicerole', 'Device Roles'),
|
||||
get_model_item('dcim', 'platform', 'Platforms'),
|
||||
get_model_item('dcim', 'virtualchassis', 'Virtual Chassis'),
|
||||
get_model_item('dcim', 'virtualdevicecontext', 'Virtual Device Contexts'),
|
||||
get_model_item('dcim', 'device', _('Devices')),
|
||||
get_model_item('dcim', 'module', _('Modules')),
|
||||
get_model_item('dcim', 'devicerole', _('Device Roles')),
|
||||
get_model_item('dcim', 'platform', _('Platforms')),
|
||||
get_model_item('dcim', 'virtualchassis', _('Virtual Chassis')),
|
||||
get_model_item('dcim', 'virtualdevicecontext', _('Virtual Device Contexts')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Device Types',
|
||||
label=_('Device Types'),
|
||||
items=(
|
||||
get_model_item('dcim', 'devicetype', 'Device Types'),
|
||||
get_model_item('dcim', 'moduletype', 'Module Types'),
|
||||
get_model_item('dcim', 'manufacturer', 'Manufacturers'),
|
||||
get_model_item('dcim', 'devicetype', _('Device Types')),
|
||||
get_model_item('dcim', 'moduletype', _('Module Types')),
|
||||
get_model_item('dcim', 'manufacturer', _('Manufacturers')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Device Components',
|
||||
label=_('Device Components'),
|
||||
items=(
|
||||
get_model_item('dcim', 'interface', 'Interfaces', actions=['import']),
|
||||
get_model_item('dcim', 'frontport', 'Front Ports', actions=['import']),
|
||||
get_model_item('dcim', 'rearport', 'Rear Ports', actions=['import']),
|
||||
get_model_item('dcim', 'consoleport', 'Console Ports', actions=['import']),
|
||||
get_model_item('dcim', 'consoleserverport', 'Console Server Ports', actions=['import']),
|
||||
get_model_item('dcim', 'powerport', 'Power Ports', actions=['import']),
|
||||
get_model_item('dcim', 'poweroutlet', 'Power Outlets', actions=['import']),
|
||||
get_model_item('dcim', 'modulebay', 'Module Bays', actions=['import']),
|
||||
get_model_item('dcim', 'devicebay', 'Device Bays', actions=['import']),
|
||||
get_model_item('dcim', 'inventoryitem', 'Inventory Items', actions=['import']),
|
||||
get_model_item('dcim', 'inventoryitemrole', 'Inventory Item Roles'),
|
||||
get_model_item('dcim', 'interface', _('Interfaces'), actions=['import']),
|
||||
get_model_item('dcim', 'frontport', _('Front Ports'), actions=['import']),
|
||||
get_model_item('dcim', 'rearport', _('Rear Ports'), actions=['import']),
|
||||
get_model_item('dcim', 'consoleport', _('Console Ports'), actions=['import']),
|
||||
get_model_item('dcim', 'consoleserverport', _('Console Server Ports'), actions=['import']),
|
||||
get_model_item('dcim', 'powerport', _('Power Ports'), actions=['import']),
|
||||
get_model_item('dcim', 'poweroutlet', _('Power Outlets'), actions=['import']),
|
||||
get_model_item('dcim', 'modulebay', _('Module Bays'), actions=['import']),
|
||||
get_model_item('dcim', 'devicebay', _('Device Bays'), actions=['import']),
|
||||
get_model_item('dcim', 'inventoryitem', _('Inventory Items'), actions=['import']),
|
||||
get_model_item('dcim', 'inventoryitemrole', _('Inventory Item Roles')),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
CONNECTIONS_MENU = Menu(
|
||||
label='Connections',
|
||||
label=_('Connections'),
|
||||
icon_class='mdi mdi-connection',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='Connections',
|
||||
label=_('Connections'),
|
||||
items=(
|
||||
get_model_item('dcim', 'cable', 'Cables', actions=['import']),
|
||||
get_model_item('wireless', 'wirelesslink', 'Wireless Links', actions=['import']),
|
||||
get_model_item('dcim', 'cable', _('Cables'), actions=['import']),
|
||||
get_model_item('wireless', 'wirelesslink', _('Wireless Links'), actions=['import']),
|
||||
MenuItem(
|
||||
link='dcim:interface_connections_list',
|
||||
link_text='Interface Connections',
|
||||
link_text=_('Interface Connections'),
|
||||
permissions=['dcim.view_interface']
|
||||
),
|
||||
MenuItem(
|
||||
link='dcim:console_connections_list',
|
||||
link_text='Console Connections',
|
||||
link_text=_('Console Connections'),
|
||||
permissions=['dcim.view_consoleport']
|
||||
),
|
||||
MenuItem(
|
||||
link='dcim:power_connections_list',
|
||||
link_text='Power Connections',
|
||||
link_text=_('Power Connections'),
|
||||
permissions=['dcim.view_powerport']
|
||||
),
|
||||
),
|
||||
@ -122,192 +123,192 @@ CONNECTIONS_MENU = Menu(
|
||||
)
|
||||
|
||||
WIRELESS_MENU = Menu(
|
||||
label='Wireless',
|
||||
label=_('Wireless'),
|
||||
icon_class='mdi mdi-wifi',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='Wireless',
|
||||
label=_('Wireless'),
|
||||
items=(
|
||||
get_model_item('wireless', 'wirelesslan', 'Wireless LANs'),
|
||||
get_model_item('wireless', 'wirelesslangroup', 'Wireless LAN Groups'),
|
||||
get_model_item('wireless', 'wirelesslan', _('Wireless LANs')),
|
||||
get_model_item('wireless', 'wirelesslangroup', _('Wireless LAN Groups')),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
IPAM_MENU = Menu(
|
||||
label='IPAM',
|
||||
label=_('IPAM'),
|
||||
icon_class='mdi mdi-counter',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='IP Addresses',
|
||||
label=_('IP Addresses'),
|
||||
items=(
|
||||
get_model_item('ipam', 'ipaddress', 'IP Addresses'),
|
||||
get_model_item('ipam', 'iprange', 'IP Ranges'),
|
||||
get_model_item('ipam', 'ipaddress', _('IP Addresses')),
|
||||
get_model_item('ipam', 'iprange', _('IP Ranges')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Prefixes',
|
||||
label=_('Prefixes'),
|
||||
items=(
|
||||
get_model_item('ipam', 'prefix', 'Prefixes'),
|
||||
get_model_item('ipam', 'role', 'Prefix & VLAN Roles'),
|
||||
get_model_item('ipam', 'prefix', _('Prefixes')),
|
||||
get_model_item('ipam', 'role', _('Prefix & VLAN Roles')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='ASNs',
|
||||
label=_('ASNs'),
|
||||
items=(
|
||||
get_model_item('ipam', 'asn', 'ASNs'),
|
||||
get_model_item('ipam', 'asn', _('ASNs')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Aggregates',
|
||||
label=_('Aggregates'),
|
||||
items=(
|
||||
get_model_item('ipam', 'aggregate', 'Aggregates'),
|
||||
get_model_item('ipam', 'rir', 'RIRs'),
|
||||
get_model_item('ipam', 'aggregate', _('Aggregates')),
|
||||
get_model_item('ipam', 'rir', _('RIRs')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='VRFs',
|
||||
label=_('VRFs'),
|
||||
items=(
|
||||
get_model_item('ipam', 'vrf', 'VRFs'),
|
||||
get_model_item('ipam', 'routetarget', 'Route Targets'),
|
||||
get_model_item('ipam', 'vrf', _('VRFs')),
|
||||
get_model_item('ipam', 'routetarget', _('Route Targets')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='VLANs',
|
||||
label=_('VLANs'),
|
||||
items=(
|
||||
get_model_item('ipam', 'vlan', 'VLANs'),
|
||||
get_model_item('ipam', 'vlangroup', 'VLAN Groups'),
|
||||
get_model_item('ipam', 'vlan', _('VLANs')),
|
||||
get_model_item('ipam', 'vlangroup', _('VLAN Groups')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Other',
|
||||
label=_('Other'),
|
||||
items=(
|
||||
get_model_item('ipam', 'fhrpgroup', 'FHRP Groups'),
|
||||
get_model_item('ipam', 'servicetemplate', 'Service Templates'),
|
||||
get_model_item('ipam', 'service', 'Services'),
|
||||
get_model_item('ipam', 'fhrpgroup', _('FHRP Groups')),
|
||||
get_model_item('ipam', 'servicetemplate', _('Service Templates')),
|
||||
get_model_item('ipam', 'service', _('Services')),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
OVERLAY_MENU = Menu(
|
||||
label='Overlay',
|
||||
label=_('Overlay'),
|
||||
icon_class='mdi mdi-graph-outline',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='L2VPNs',
|
||||
items=(
|
||||
get_model_item('ipam', 'l2vpn', 'L2VPNs'),
|
||||
get_model_item('ipam', 'l2vpntermination', 'Terminations'),
|
||||
get_model_item('ipam', 'l2vpn', _('L2VPNs')),
|
||||
get_model_item('ipam', 'l2vpntermination', _('Terminations')),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
VIRTUALIZATION_MENU = Menu(
|
||||
label='Virtualization',
|
||||
label=_('Virtualization'),
|
||||
icon_class='mdi mdi-monitor',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='Virtual Machines',
|
||||
label=_('Virtual Machines'),
|
||||
items=(
|
||||
get_model_item('virtualization', 'virtualmachine', 'Virtual Machines'),
|
||||
get_model_item('virtualization', 'vminterface', 'Interfaces', actions=['import']),
|
||||
get_model_item('virtualization', 'virtualmachine', _('Virtual Machines')),
|
||||
get_model_item('virtualization', 'vminterface', _('Interfaces'), actions=['import']),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Clusters',
|
||||
label=_('Clusters'),
|
||||
items=(
|
||||
get_model_item('virtualization', 'cluster', 'Clusters'),
|
||||
get_model_item('virtualization', 'clustertype', 'Cluster Types'),
|
||||
get_model_item('virtualization', 'clustergroup', 'Cluster Groups'),
|
||||
get_model_item('virtualization', 'cluster', _('Clusters')),
|
||||
get_model_item('virtualization', 'clustertype', _('Cluster Types')),
|
||||
get_model_item('virtualization', 'clustergroup', _('Cluster Groups')),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
CIRCUITS_MENU = Menu(
|
||||
label='Circuits',
|
||||
label=_('Circuits'),
|
||||
icon_class='mdi mdi-transit-connection-variant',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='Circuits',
|
||||
label=_('Circuits'),
|
||||
items=(
|
||||
get_model_item('circuits', 'circuit', 'Circuits'),
|
||||
get_model_item('circuits', 'circuittype', 'Circuit Types'),
|
||||
get_model_item('circuits', 'circuit', _('Circuits')),
|
||||
get_model_item('circuits', 'circuittype', _('Circuit Types')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Providers',
|
||||
label=_('Providers'),
|
||||
items=(
|
||||
get_model_item('circuits', 'provider', 'Providers'),
|
||||
get_model_item('circuits', 'providernetwork', 'Provider Networks'),
|
||||
get_model_item('circuits', 'provider', _('Providers')),
|
||||
get_model_item('circuits', 'providernetwork', _('Provider Networks')),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
POWER_MENU = Menu(
|
||||
label='Power',
|
||||
label=_('Power'),
|
||||
icon_class='mdi mdi-flash',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='Power',
|
||||
label=_('Power'),
|
||||
items=(
|
||||
get_model_item('dcim', 'powerfeed', 'Power Feeds'),
|
||||
get_model_item('dcim', 'powerpanel', 'Power Panels'),
|
||||
get_model_item('dcim', 'powerfeed', _('Power Feeds')),
|
||||
get_model_item('dcim', 'powerpanel', _('Power Panels')),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
OTHER_MENU = Menu(
|
||||
label='Other',
|
||||
label=_('Other'),
|
||||
icon_class='mdi mdi-notification-clear-all',
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label='Logging',
|
||||
label=_('Logging'),
|
||||
items=(
|
||||
get_model_item('extras', 'journalentry', 'Journal Entries', actions=[]),
|
||||
get_model_item('extras', 'objectchange', 'Change Log', actions=[]),
|
||||
get_model_item('extras', 'journalentry', _('Journal Entries'), actions=[]),
|
||||
get_model_item('extras', 'objectchange', _('Change Log'), actions=[]),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Customization',
|
||||
label=_('Customization'),
|
||||
items=(
|
||||
get_model_item('extras', 'customfield', 'Custom Fields'),
|
||||
get_model_item('extras', 'customlink', 'Custom Links'),
|
||||
get_model_item('extras', 'exporttemplate', 'Export Templates'),
|
||||
get_model_item('extras', 'savedfilter', 'Saved Filters'),
|
||||
get_model_item('extras', 'customfield', _('Custom Fields')),
|
||||
get_model_item('extras', 'customlink', _('Custom Links')),
|
||||
get_model_item('extras', 'exporttemplate', _('Export Templates')),
|
||||
get_model_item('extras', 'savedfilter', _('Saved Filters')),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Integrations',
|
||||
label=_('Integrations'),
|
||||
items=(
|
||||
get_model_item('extras', 'webhook', 'Webhooks'),
|
||||
get_model_item('extras', 'webhook', _('Webhooks')),
|
||||
MenuItem(
|
||||
link='extras:report_list',
|
||||
link_text='Reports',
|
||||
link_text=_('Reports'),
|
||||
permissions=['extras.view_report']
|
||||
),
|
||||
MenuItem(
|
||||
link='extras:script_list',
|
||||
link_text='Scripts',
|
||||
link_text=_('Scripts'),
|
||||
permissions=['extras.view_script']
|
||||
),
|
||||
MenuItem(
|
||||
link='extras:jobresult_list',
|
||||
link_text='Job Results',
|
||||
link_text=_('Job Results'),
|
||||
permissions=['extras.view_jobresult'],
|
||||
),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label='Other',
|
||||
label=_('Other'),
|
||||
items=(
|
||||
get_model_item('extras', 'tag', 'Tags'),
|
||||
get_model_item('extras', 'configcontext', 'Config Contexts', actions=['add']),
|
||||
get_model_item('extras', 'configcontext', _('Config Contexts'), actions=['add']),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -342,7 +343,7 @@ if registry['plugins']['menu_items']:
|
||||
for label, items in registry['plugins']['menu_items'].items()
|
||||
]
|
||||
plugins_menu = Menu(
|
||||
label="Plugins",
|
||||
label=_("Plugins"),
|
||||
icon_class="mdi mdi-puzzle",
|
||||
groups=groups
|
||||
)
|
||||
|
@ -1,3 +1,4 @@
|
||||
from django.utils.translation import gettext as _
|
||||
from netbox.registry import registry
|
||||
from users.preferences import UserPreference
|
||||
from utilities.paginator import EnhancedPaginator
|
||||
@ -13,7 +14,7 @@ PREFERENCES = {
|
||||
|
||||
# User interface
|
||||
'ui.colormode': UserPreference(
|
||||
label='Color mode',
|
||||
label=_('Color mode'),
|
||||
choices=(
|
||||
('light', 'Light'),
|
||||
('dark', 'Dark'),
|
||||
@ -21,25 +22,25 @@ PREFERENCES = {
|
||||
default='light',
|
||||
),
|
||||
'pagination.per_page': UserPreference(
|
||||
label='Page length',
|
||||
label=_('Page length'),
|
||||
choices=get_page_lengths(),
|
||||
description='The number of objects to display per page',
|
||||
description=_('The number of objects to display per page'),
|
||||
coerce=lambda x: int(x)
|
||||
),
|
||||
'pagination.placement': UserPreference(
|
||||
label='Paginator placement',
|
||||
label=_('Paginator placement'),
|
||||
choices=(
|
||||
('bottom', 'Bottom'),
|
||||
('top', 'Top'),
|
||||
('both', 'Both'),
|
||||
),
|
||||
description='Where the paginator controls will be displayed relative to a table',
|
||||
description=_('Where the paginator controls will be displayed relative to a table'),
|
||||
default='bottom'
|
||||
),
|
||||
|
||||
# Miscellaneous
|
||||
'data_format': UserPreference(
|
||||
label='Data format',
|
||||
label=_('Data format'),
|
||||
choices=(
|
||||
('json', 'JSON'),
|
||||
('yaml', 'YAML'),
|
||||
|
@ -1,5 +1,6 @@
|
||||
import django_filters
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from netbox.filtersets import ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet
|
||||
from utilities.filters import ContentTypeFilter, TreeNodeMultipleChoiceFilter
|
||||
@ -25,13 +26,13 @@ __all__ = (
|
||||
class ContactGroupFilterSet(OrganizationalModelFilterSet):
|
||||
parent_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ContactGroup.objects.all(),
|
||||
label='Contact group (ID)',
|
||||
label=_('Contact group (ID)'),
|
||||
)
|
||||
parent = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='parent__slug',
|
||||
queryset=ContactGroup.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Contact group (slug)',
|
||||
label=_('Contact group (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -51,14 +52,14 @@ class ContactFilterSet(NetBoxModelFilterSet):
|
||||
queryset=ContactGroup.objects.all(),
|
||||
field_name='group',
|
||||
lookup_expr='in',
|
||||
label='Contact group (ID)',
|
||||
label=_('Contact group (ID)'),
|
||||
)
|
||||
group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=ContactGroup.objects.all(),
|
||||
field_name='group',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Contact group (slug)',
|
||||
label=_('Contact group (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -83,17 +84,17 @@ class ContactAssignmentFilterSet(ChangeLoggedModelFilterSet):
|
||||
content_type = ContentTypeFilter()
|
||||
contact_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Contact.objects.all(),
|
||||
label='Contact (ID)',
|
||||
label=_('Contact (ID)'),
|
||||
)
|
||||
role_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ContactRole.objects.all(),
|
||||
label='Contact role (ID)',
|
||||
label=_('Contact role (ID)'),
|
||||
)
|
||||
role = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='role__slug',
|
||||
queryset=ContactRole.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Contact role (slug)',
|
||||
label=_('Contact role (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -105,18 +106,18 @@ class ContactModelFilterSet(django_filters.FilterSet):
|
||||
contact = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='contacts__contact',
|
||||
queryset=Contact.objects.all(),
|
||||
label='Contact',
|
||||
label=_('Contact'),
|
||||
)
|
||||
contact_role = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='contacts__role',
|
||||
queryset=ContactRole.objects.all(),
|
||||
label='Contact Role'
|
||||
label=_('Contact Role')
|
||||
)
|
||||
contact_group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=ContactGroup.objects.all(),
|
||||
field_name='contacts__contact__group',
|
||||
lookup_expr='in',
|
||||
label='Contact group',
|
||||
label=_('Contact group'),
|
||||
)
|
||||
|
||||
|
||||
@ -127,13 +128,13 @@ class ContactModelFilterSet(django_filters.FilterSet):
|
||||
class TenantGroupFilterSet(OrganizationalModelFilterSet):
|
||||
parent_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=TenantGroup.objects.all(),
|
||||
label='Tenant group (ID)',
|
||||
label=_('Tenant group (ID)'),
|
||||
)
|
||||
parent = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='parent__slug',
|
||||
queryset=TenantGroup.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Tenant group (slug)',
|
||||
label=_('Tenant group (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -146,14 +147,14 @@ class TenantFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
||||
queryset=TenantGroup.objects.all(),
|
||||
field_name='group',
|
||||
lookup_expr='in',
|
||||
label='Tenant group (ID)',
|
||||
label=_('Tenant group (ID)'),
|
||||
)
|
||||
group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=TenantGroup.objects.all(),
|
||||
field_name='group',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Tenant group (slug)',
|
||||
label=_('Tenant group (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -179,22 +180,22 @@ class TenancyFilterSet(django_filters.FilterSet):
|
||||
queryset=TenantGroup.objects.all(),
|
||||
field_name='tenant__group',
|
||||
lookup_expr='in',
|
||||
label='Tenant Group (ID)',
|
||||
label=_('Tenant Group (ID)'),
|
||||
)
|
||||
tenant_group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=TenantGroup.objects.all(),
|
||||
field_name='tenant__group',
|
||||
to_field_name='slug',
|
||||
lookup_expr='in',
|
||||
label='Tenant Group (slug)',
|
||||
label=_('Tenant Group (slug)'),
|
||||
)
|
||||
tenant_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Tenant.objects.all(),
|
||||
label='Tenant (ID)',
|
||||
label=_('Tenant (ID)'),
|
||||
)
|
||||
tenant = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Tenant.objects.all(),
|
||||
field_name='tenant__slug',
|
||||
to_field_name='slug',
|
||||
label='Tenant (slug)',
|
||||
label=_('Tenant (slug)'),
|
||||
)
|
||||
|
@ -1,3 +1,4 @@
|
||||
from django.utils.translation import gettext as _
|
||||
from netbox.forms import NetBoxModelCSVForm
|
||||
from tenancy.models import *
|
||||
from utilities.forms import CSVModelChoiceField, SlugField
|
||||
@ -20,7 +21,7 @@ class TenantGroupCSVForm(NetBoxModelCSVForm):
|
||||
queryset=TenantGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent group'
|
||||
help_text=_('Parent group')
|
||||
)
|
||||
slug = SlugField()
|
||||
|
||||
@ -35,7 +36,7 @@ class TenantCSVForm(NetBoxModelCSVForm):
|
||||
queryset=TenantGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned group'
|
||||
help_text=_('Assigned group')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -52,7 +53,7 @@ class ContactGroupCSVForm(NetBoxModelCSVForm):
|
||||
queryset=ContactGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent group'
|
||||
help_text=_('Parent group')
|
||||
)
|
||||
slug = SlugField()
|
||||
|
||||
@ -74,7 +75,7 @@ class ContactCSVForm(NetBoxModelCSVForm):
|
||||
queryset=ContactGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned group'
|
||||
help_text=_('Assigned group')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -3,6 +3,7 @@ from django.contrib.auth.models import Group, User
|
||||
from django.contrib.admin.widgets import FilteredSelectMultiple
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import FieldError, ValidationError
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from users.constants import CONSTRAINT_TOKEN_USER, OBJECTPERMISSION_OBJECT_TYPES
|
||||
from users.models import ObjectPermission, Token
|
||||
@ -46,7 +47,7 @@ class GroupAdminForm(forms.ModelForm):
|
||||
class TokenAdminForm(forms.ModelForm):
|
||||
key = forms.CharField(
|
||||
required=False,
|
||||
help_text="If no key is provided, one will be generated automatically."
|
||||
help_text=_("If no key is provided, one will be generated automatically.")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -70,10 +71,10 @@ class ObjectPermissionForm(forms.ModelForm):
|
||||
model = ObjectPermission
|
||||
exclude = []
|
||||
help_texts = {
|
||||
'actions': 'Actions granted in addition to those listed above',
|
||||
'constraints': 'JSON expression of a queryset filter that will return only permitted objects. Leave null '
|
||||
'to match all objects of this type. A list of multiple objects will result in a logical OR '
|
||||
'operation.'
|
||||
'actions': _('Actions granted in addition to those listed above'),
|
||||
'constraints': _('JSON expression of a queryset filter that will return only permitted objects. Leave null '
|
||||
'to match all objects of this type. A list of multiple objects will result in a logical OR '
|
||||
'operation.')
|
||||
}
|
||||
labels = {
|
||||
'actions': 'Additional actions'
|
||||
|
@ -1,6 +1,7 @@
|
||||
import django_filters
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from netbox.filtersets import BaseFilterSet
|
||||
from users.models import ObjectPermission, Token
|
||||
@ -15,7 +16,7 @@ __all__ = (
|
||||
class GroupFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -31,18 +32,18 @@ class GroupFilterSet(BaseFilterSet):
|
||||
class UserFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='groups',
|
||||
queryset=Group.objects.all(),
|
||||
label='Group',
|
||||
label=_('Group'),
|
||||
)
|
||||
group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='groups__name',
|
||||
queryset=Group.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Group (name)',
|
||||
label=_('Group (name)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -63,18 +64,18 @@ class UserFilterSet(BaseFilterSet):
|
||||
class TokenFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
user_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='user',
|
||||
queryset=User.objects.all(),
|
||||
label='User',
|
||||
label=_('User'),
|
||||
)
|
||||
user = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='user__username',
|
||||
queryset=User.objects.all(),
|
||||
to_field_name='username',
|
||||
label='User (name)',
|
||||
label=_('User (name)'),
|
||||
)
|
||||
created = django_filters.DateTimeFilter()
|
||||
created__gte = django_filters.DateTimeFilter(
|
||||
@ -111,29 +112,29 @@ class TokenFilterSet(BaseFilterSet):
|
||||
class ObjectPermissionFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
label=_('Search'),
|
||||
)
|
||||
user_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='users',
|
||||
queryset=User.objects.all(),
|
||||
label='User',
|
||||
label=_('User'),
|
||||
)
|
||||
user = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='users__username',
|
||||
queryset=User.objects.all(),
|
||||
to_field_name='username',
|
||||
label='User (name)',
|
||||
label=_('User (name)'),
|
||||
)
|
||||
group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='groups',
|
||||
queryset=Group.objects.all(),
|
||||
label='Group',
|
||||
label=_('Group'),
|
||||
)
|
||||
group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='groups__name',
|
||||
queryset=Group.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Group (name)',
|
||||
label=_('Group (name)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -3,6 +3,7 @@ from django.conf import settings
|
||||
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm
|
||||
from django.contrib.postgres.forms import SimpleArrayField
|
||||
from django.utils.html import mark_safe
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from ipam.formfields import IPNetworkFormField
|
||||
from netbox.preferences import PREFERENCES
|
||||
@ -100,14 +101,14 @@ class UserConfigForm(BootstrapMixin, forms.ModelForm, metaclass=UserConfigFormMe
|
||||
class TokenForm(BootstrapMixin, forms.ModelForm):
|
||||
key = forms.CharField(
|
||||
required=False,
|
||||
help_text="If no key is provided, one will be generated automatically."
|
||||
help_text=_("If no key is provided, one will be generated automatically.")
|
||||
)
|
||||
allowed_ips = SimpleArrayField(
|
||||
base_field=IPNetworkFormField(),
|
||||
required=False,
|
||||
label='Allowed IPs',
|
||||
help_text='Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
|
||||
'Example: <code>10.1.1.0/24,192.168.10.16/32,2001:db8:1::/64</code>',
|
||||
label=_('Allowed IPs'),
|
||||
help_text=_('Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
|
||||
'Example: <code>10.1.1.0/24,192.168.10.16/32,2001:db8:1::/64</code>'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -10,6 +10,7 @@ from django.db import models
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext as _
|
||||
from netaddr import IPNetwork
|
||||
|
||||
from ipam.fields import IPNetworkField
|
||||
@ -216,7 +217,7 @@ class Token(models.Model):
|
||||
)
|
||||
write_enabled = models.BooleanField(
|
||||
default=True,
|
||||
help_text='Permit create/update/delete operations using this key'
|
||||
help_text=_('Permit create/update/delete operations using this key')
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
@ -227,8 +228,8 @@ class Token(models.Model):
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Allowed IPs',
|
||||
help_text='Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
|
||||
'Ex: "10.1.1.0/24, 192.168.10.16/32, 2001:DB8:1::/64"',
|
||||
help_text=_('Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
|
||||
'Ex: "10.1.1.0/24, 192.168.10.16/32, 2001:DB8:1::/64"'),
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
@ -304,12 +305,12 @@ class ObjectPermission(models.Model):
|
||||
)
|
||||
actions = ArrayField(
|
||||
base_field=models.CharField(max_length=30),
|
||||
help_text="The list of actions granted by this permission"
|
||||
help_text=_("The list of actions granted by this permission")
|
||||
)
|
||||
constraints = models.JSONField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Queryset filter matching the applicable objects of the selected type(s)"
|
||||
help_text=_("Queryset filter matching the applicable objects of the selected type(s)")
|
||||
)
|
||||
|
||||
objects = RestrictedQuerySet.as_manager()
|
||||
|
@ -5,6 +5,7 @@ from django import forms
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from utilities.choices import unpack_grouped_choices
|
||||
from utilities.forms.utils import parse_csv, validate_csv
|
||||
@ -50,9 +51,9 @@ class CSVDataField(forms.CharField):
|
||||
if not self.initial:
|
||||
self.initial = ','.join(self.required_fields) + '\n'
|
||||
if not self.help_text:
|
||||
self.help_text = 'Enter the list of column headers followed by one line per record to be imported, using ' \
|
||||
'commas to separate values. Multi-line data and values containing commas may be wrapped ' \
|
||||
'in double quotes.'
|
||||
self.help_text = _('Enter the list of column headers followed by one line per record to be imported, using '
|
||||
'commas to separate values. Multi-line data and values containing commas may be wrapped '
|
||||
'in double quotes.')
|
||||
|
||||
def to_python(self, value):
|
||||
reader = csv.reader(StringIO(value.strip()))
|
||||
|
@ -1,6 +1,7 @@
|
||||
import re
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from utilities.forms.constants import *
|
||||
from utilities.forms.utils import expand_alphanumeric_pattern, expand_ipaddress_pattern
|
||||
@ -42,8 +43,8 @@ class ExpandableIPAddressField(forms.CharField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if not self.help_text:
|
||||
self.help_text = 'Specify a numeric range to create multiple IPs.<br />'\
|
||||
'Example: <code>192.0.2.[1,5,100-254]/24</code>'
|
||||
self.help_text = _('Specify a numeric range to create multiple IPs.<br />'
|
||||
'Example: <code>192.0.2.[1,5,100-254]/24</code>')
|
||||
|
||||
def to_python(self, value):
|
||||
# Hackish address family detection but it's all we have to work with
|
||||
|
@ -4,6 +4,7 @@ from django import forms
|
||||
from django.db.models import Count
|
||||
from django.forms.fields import JSONField as _JSONField, InvalidJSONInput
|
||||
from django.templatetags.static import static
|
||||
from django.utils.translation import gettext as _
|
||||
from netaddr import AddrFormatError, EUI
|
||||
|
||||
from utilities.forms import widgets
|
||||
@ -45,7 +46,7 @@ class SlugField(forms.SlugField):
|
||||
slug_source: Name of the form field from which the slug value will be derived
|
||||
"""
|
||||
widget = widgets.SlugWidget
|
||||
help_text = "URL-friendly unique shorthand"
|
||||
help_text = _("URL-friendly unique shorthand")
|
||||
|
||||
def __init__(self, *, slug_source='name', help_text=help_text, **kwargs):
|
||||
super().__init__(help_text=help_text, **kwargs)
|
||||
@ -97,7 +98,7 @@ class JSONField(_JSONField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if not self.help_text:
|
||||
self.help_text = 'Enter context data in <a href="https://json.org/">JSON</a> format.'
|
||||
self.help_text = _('Enter context data in <a href="https://json.org/">JSON</a> format.')
|
||||
self.widget.attrs['placeholder'] = ''
|
||||
self.widget.attrs['class'] = 'font-monospace'
|
||||
|
||||
|
@ -5,8 +5,9 @@ from io import StringIO
|
||||
|
||||
import yaml
|
||||
from django import forms
|
||||
from utilities.forms.utils import parse_csv
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from utilities.forms.utils import parse_csv
|
||||
from .choices import ImportFormatChoices
|
||||
from .widgets import APISelect, APISelectMultiple, ClearableFileInput, StaticSelect
|
||||
|
||||
@ -103,7 +104,7 @@ class BulkRenameForm(BootstrapMixin, forms.Form):
|
||||
use_regex = forms.BooleanField(
|
||||
required=False,
|
||||
initial=True,
|
||||
label='Use regular expressions'
|
||||
label=_('Use regular expressions')
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
@ -145,7 +146,7 @@ class ImportForm(BootstrapMixin, forms.Form):
|
||||
data = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.Textarea(attrs={'class': 'font-monospace'}),
|
||||
help_text="Enter object data in CSV, JSON or YAML format."
|
||||
help_text=_("Enter object data in CSV, JSON or YAML format.")
|
||||
)
|
||||
data_file = forms.FileField(
|
||||
label="Data file",
|
||||
@ -219,7 +220,7 @@ class FilterForm(BootstrapMixin, forms.Form):
|
||||
"""
|
||||
q = forms.CharField(
|
||||
required=False,
|
||||
label='Search'
|
||||
label=_('Search')
|
||||
)
|
||||
|
||||
|
||||
@ -233,7 +234,7 @@ class TableConfigForm(BootstrapMixin, forms.Form):
|
||||
widget=forms.SelectMultiple(
|
||||
attrs={'size': 10, 'class': 'form-select'}
|
||||
),
|
||||
label='Available Columns'
|
||||
label=_('Available Columns')
|
||||
)
|
||||
columns = forms.MultipleChoiceField(
|
||||
choices=[],
|
||||
@ -241,7 +242,7 @@ class TableConfigForm(BootstrapMixin, forms.Form):
|
||||
widget=forms.SelectMultiple(
|
||||
attrs={'size': 10, 'class': 'form-select'}
|
||||
),
|
||||
label='Selected Columns'
|
||||
label=_('Selected Columns')
|
||||
)
|
||||
|
||||
def __init__(self, table, *args, **kwargs):
|
||||
|
@ -1,5 +1,6 @@
|
||||
import django_filters
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import Device, DeviceRole, Platform, Region, Site, SiteGroup
|
||||
from extras.filtersets import LocalConfigContextFilterSet
|
||||
@ -38,57 +39,57 @@ class ClusterFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
lookup_expr='in',
|
||||
label='Region (ID)',
|
||||
label=_('Region (ID)'),
|
||||
)
|
||||
region = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Region (slug)',
|
||||
label=_('Region (slug)'),
|
||||
)
|
||||
site_group_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='site__group',
|
||||
lookup_expr='in',
|
||||
label='Site group (ID)',
|
||||
label=_('Site group (ID)'),
|
||||
)
|
||||
site_group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='site__group',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Site group (slug)',
|
||||
label=_('Site group (slug)'),
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site (ID)',
|
||||
label=_('Site (ID)'),
|
||||
)
|
||||
site = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='site__slug',
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
label='Parent group (ID)',
|
||||
label=_('Parent group (ID)'),
|
||||
)
|
||||
group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='group__slug',
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Parent group (slug)',
|
||||
label=_('Parent group (slug)'),
|
||||
)
|
||||
type_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ClusterType.objects.all(),
|
||||
label='Cluster type (ID)',
|
||||
label=_('Cluster type (ID)'),
|
||||
)
|
||||
type = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='type__slug',
|
||||
queryset=ClusterType.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Cluster type (slug)',
|
||||
label=_('Cluster type (slug)'),
|
||||
)
|
||||
status = django_filters.MultipleChoiceFilter(
|
||||
choices=ClusterStatusChoices,
|
||||
@ -121,111 +122,111 @@ class VirtualMachineFilterSet(
|
||||
cluster_group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='cluster__group',
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
label='Cluster group (ID)',
|
||||
label=_('Cluster group (ID)'),
|
||||
)
|
||||
cluster_group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='cluster__group__slug',
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Cluster group (slug)',
|
||||
label=_('Cluster group (slug)'),
|
||||
)
|
||||
cluster_type_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='cluster__type',
|
||||
queryset=ClusterType.objects.all(),
|
||||
label='Cluster type (ID)',
|
||||
label=_('Cluster type (ID)'),
|
||||
)
|
||||
cluster_type = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='cluster__type__slug',
|
||||
queryset=ClusterType.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Cluster type (slug)',
|
||||
label=_('Cluster type (slug)'),
|
||||
)
|
||||
cluster_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Cluster.objects.all(),
|
||||
label='Cluster (ID)',
|
||||
label=_('Cluster (ID)'),
|
||||
)
|
||||
cluster = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='cluster__name',
|
||||
queryset=Cluster.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Cluster',
|
||||
label=_('Cluster'),
|
||||
)
|
||||
device_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Device.objects.all(),
|
||||
label='Device (ID)',
|
||||
label=_('Device (ID)'),
|
||||
)
|
||||
device = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='device__name',
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Device',
|
||||
label=_('Device'),
|
||||
)
|
||||
region_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
lookup_expr='in',
|
||||
label='Region (ID)',
|
||||
label=_('Region (ID)'),
|
||||
)
|
||||
region = TreeNodeMultipleChoiceFilter(
|
||||
queryset=Region.objects.all(),
|
||||
field_name='site__region',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Region (slug)',
|
||||
label=_('Region (slug)'),
|
||||
)
|
||||
site_group_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='site__group',
|
||||
lookup_expr='in',
|
||||
label='Site group (ID)',
|
||||
label=_('Site group (ID)'),
|
||||
)
|
||||
site_group = TreeNodeMultipleChoiceFilter(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
field_name='site__group',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label='Site group (slug)',
|
||||
label=_('Site group (slug)'),
|
||||
)
|
||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site (ID)',
|
||||
label=_('Site (ID)'),
|
||||
)
|
||||
site = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='site__slug',
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Site (slug)',
|
||||
label=_('Site (slug)'),
|
||||
)
|
||||
name = MultiValueCharFilter(
|
||||
lookup_expr='iexact'
|
||||
)
|
||||
role_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=DeviceRole.objects.all(),
|
||||
label='Role (ID)',
|
||||
label=_('Role (ID)'),
|
||||
)
|
||||
role = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='role__slug',
|
||||
queryset=DeviceRole.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Role (slug)',
|
||||
label=_('Role (slug)'),
|
||||
)
|
||||
platform_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=Platform.objects.all(),
|
||||
label='Platform (ID)',
|
||||
label=_('Platform (ID)'),
|
||||
)
|
||||
platform = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='platform__slug',
|
||||
queryset=Platform.objects.all(),
|
||||
to_field_name='slug',
|
||||
label='Platform (slug)',
|
||||
label=_('Platform (slug)'),
|
||||
)
|
||||
mac_address = MultiValueMACAddressFilter(
|
||||
field_name='interfaces__mac_address',
|
||||
label='MAC address',
|
||||
label=_('MAC address'),
|
||||
)
|
||||
has_primary_ip = django_filters.BooleanFilter(
|
||||
method='_has_primary_ip',
|
||||
label='Has a primary IP',
|
||||
label=_('Has a primary IP'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -251,48 +252,48 @@ class VMInterfaceFilterSet(NetBoxModelFilterSet):
|
||||
cluster_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_machine__cluster',
|
||||
queryset=Cluster.objects.all(),
|
||||
label='Cluster (ID)',
|
||||
label=_('Cluster (ID)'),
|
||||
)
|
||||
cluster = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_machine__cluster__name',
|
||||
queryset=Cluster.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Cluster',
|
||||
label=_('Cluster'),
|
||||
)
|
||||
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_machine',
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
label='Virtual machine (ID)',
|
||||
label=_('Virtual machine (ID)'),
|
||||
)
|
||||
virtual_machine = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_machine__name',
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Virtual machine',
|
||||
label=_('Virtual machine'),
|
||||
)
|
||||
parent_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='parent',
|
||||
queryset=VMInterface.objects.all(),
|
||||
label='Parent interface (ID)',
|
||||
label=_('Parent interface (ID)'),
|
||||
)
|
||||
bridge_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='bridge',
|
||||
queryset=VMInterface.objects.all(),
|
||||
label='Bridged interface (ID)',
|
||||
label=_('Bridged interface (ID)'),
|
||||
)
|
||||
mac_address = MultiValueMACAddressFilter(
|
||||
label='MAC address',
|
||||
label=_('MAC address'),
|
||||
)
|
||||
vrf_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vrf',
|
||||
queryset=VRF.objects.all(),
|
||||
label='VRF',
|
||||
label=_('VRF'),
|
||||
)
|
||||
vrf = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vrf__rd',
|
||||
queryset=VRF.objects.all(),
|
||||
to_field_name='rd',
|
||||
label='VRF (RD)',
|
||||
label=_('VRF (RD)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from utilities.forms import BootstrapMixin, ExpandableNameField, form_from_model
|
||||
from virtualization.models import VMInterface, VirtualMachine
|
||||
@ -14,7 +15,7 @@ class VirtualMachineBulkAddComponentForm(BootstrapMixin, forms.Form):
|
||||
widget=forms.MultipleHiddenInput()
|
||||
)
|
||||
name = ExpandableNameField(
|
||||
label='Name'
|
||||
label=_('Name')
|
||||
)
|
||||
|
||||
def clean_tags(self):
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.choices import InterfaceModeChoices
|
||||
from dcim.constants import INTERFACE_MTU_MAX, INTERFACE_MTU_MIN
|
||||
@ -90,7 +91,7 @@ class ClusterBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
comments = CommentField(
|
||||
widget=SmallTextarea,
|
||||
label='Comments'
|
||||
label=_('Comments')
|
||||
)
|
||||
|
||||
model = Cluster
|
||||
@ -147,15 +148,15 @@ class VirtualMachineBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
vcpus = forms.IntegerField(
|
||||
required=False,
|
||||
label='vCPUs'
|
||||
label=_('vCPUs')
|
||||
)
|
||||
memory = forms.IntegerField(
|
||||
required=False,
|
||||
label='Memory (MB)'
|
||||
label=_('Memory (MB)')
|
||||
)
|
||||
disk = forms.IntegerField(
|
||||
required=False,
|
||||
label='Disk (GB)'
|
||||
label=_('Disk (GB)')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -163,7 +164,7 @@ class VirtualMachineBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
comments = CommentField(
|
||||
widget=SmallTextarea,
|
||||
label='Comments'
|
||||
label=_('Comments')
|
||||
)
|
||||
|
||||
model = VirtualMachine
|
||||
@ -199,7 +200,7 @@ class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False,
|
||||
min_value=INTERFACE_MTU_MIN,
|
||||
max_value=INTERFACE_MTU_MAX,
|
||||
label='MTU'
|
||||
label=_('MTU')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=100,
|
||||
@ -213,7 +214,7 @@ class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
vlan_group = DynamicModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
label='VLAN group'
|
||||
label=_('VLAN group')
|
||||
)
|
||||
untagged_vlan = DynamicModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
@ -221,7 +222,7 @@ class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
query_params={
|
||||
'group_id': '$vlan_group',
|
||||
},
|
||||
label='Untagged VLAN'
|
||||
label=_('Untagged VLAN')
|
||||
)
|
||||
tagged_vlans = DynamicModelMultipleChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
@ -229,12 +230,12 @@ class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm):
|
||||
query_params={
|
||||
'group_id': '$vlan_group',
|
||||
},
|
||||
label='Tagged VLANs'
|
||||
label=_('Tagged VLANs')
|
||||
)
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
|
||||
model = VMInterface
|
||||
|
@ -1,5 +1,6 @@
|
||||
from dcim.choices import InterfaceModeChoices
|
||||
from dcim.models import Device, DeviceRole, Platform, Site
|
||||
from django.utils.translation import gettext as _
|
||||
from ipam.models import VRF
|
||||
from netbox.forms import NetBoxModelCSVForm
|
||||
from tenancy.models import Tenant
|
||||
@ -36,29 +37,29 @@ class ClusterCSVForm(NetBoxModelCSVForm):
|
||||
type = CSVModelChoiceField(
|
||||
queryset=ClusterType.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Type of cluster'
|
||||
help_text=_('Type of cluster')
|
||||
)
|
||||
group = CSVModelChoiceField(
|
||||
queryset=ClusterGroup.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned cluster group'
|
||||
help_text=_('Assigned cluster group')
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=ClusterStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
site = CSVModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned site'
|
||||
help_text=_('Assigned site')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -69,25 +70,25 @@ class ClusterCSVForm(NetBoxModelCSVForm):
|
||||
class VirtualMachineCSVForm(NetBoxModelCSVForm):
|
||||
status = CSVChoiceField(
|
||||
choices=VirtualMachineStatusChoices,
|
||||
help_text='Operational status'
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
site = CSVModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned site'
|
||||
help_text=_('Assigned site')
|
||||
)
|
||||
cluster = CSVModelChoiceField(
|
||||
queryset=Cluster.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned cluster'
|
||||
help_text=_('Assigned cluster')
|
||||
)
|
||||
device = CSVModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text='Assigned device within cluster'
|
||||
help_text=_('Assigned device within cluster')
|
||||
)
|
||||
role = CSVModelChoiceField(
|
||||
queryset=DeviceRole.objects.filter(
|
||||
@ -95,19 +96,19 @@ class VirtualMachineCSVForm(NetBoxModelCSVForm):
|
||||
),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Functional role'
|
||||
help_text=_('Functional role')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
platform = CSVModelChoiceField(
|
||||
queryset=Platform.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned platform'
|
||||
help_text=_('Assigned platform')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -127,24 +128,24 @@ class VMInterfaceCSVForm(NetBoxModelCSVForm):
|
||||
queryset=VMInterface.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent interface'
|
||||
help_text=_('Parent interface')
|
||||
)
|
||||
bridge = CSVModelChoiceField(
|
||||
queryset=VMInterface.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Bridged interface'
|
||||
help_text=_('Bridged interface')
|
||||
)
|
||||
mode = CSVChoiceField(
|
||||
choices=InterfaceModeChoices,
|
||||
required=False,
|
||||
help_text='IEEE 802.1Q operational mode (for L2 interfaces)'
|
||||
help_text=_('IEEE 802.1Q operational mode (for L2 interfaces)')
|
||||
)
|
||||
vrf = CSVModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
to_field_name='rd',
|
||||
help_text='Assigned VRF'
|
||||
help_text=_('Assigned VRF')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -160,11 +160,11 @@ class VirtualMachineFilterForm(
|
||||
)
|
||||
mac_address = forms.CharField(
|
||||
required=False,
|
||||
label='MAC address'
|
||||
label=_('MAC address')
|
||||
)
|
||||
has_primary_ip = forms.NullBooleanField(
|
||||
required=False,
|
||||
label='Has a primary IP',
|
||||
label=_('Has a primary IP'),
|
||||
widget=StaticSelect(
|
||||
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||
)
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django import forms
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.forms.common import InterfaceCommonForm
|
||||
from dcim.forms.model_forms import INTERFACE_MODE_HELP_TEXT
|
||||
@ -204,7 +205,7 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
|
||||
'cluster_id': '$cluster',
|
||||
'site_id': '$site',
|
||||
},
|
||||
help_text="Optionally pin this VM to a specific host device within the cluster"
|
||||
help_text=_("Optionally pin this VM to a specific host device within the cluster")
|
||||
)
|
||||
role = DynamicModelChoiceField(
|
||||
queryset=DeviceRole.objects.all(),
|
||||
@ -240,8 +241,8 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
|
||||
'local_context_data',
|
||||
]
|
||||
help_texts = {
|
||||
'local_context_data': "Local config context data overwrites all sources contexts in the final rendered "
|
||||
"config context",
|
||||
'local_context_data': _("Local config context data overwrites all sources contexts in the final rendered "
|
||||
"config context"),
|
||||
}
|
||||
widgets = {
|
||||
"status": StaticSelect(),
|
||||
@ -297,7 +298,7 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
queryset=VMInterface.objects.all(),
|
||||
required=False,
|
||||
label='Parent interface',
|
||||
label=_('Parent interface'),
|
||||
query_params={
|
||||
'virtual_machine_id': '$virtual_machine',
|
||||
}
|
||||
@ -305,7 +306,7 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
||||
bridge = DynamicModelChoiceField(
|
||||
queryset=VMInterface.objects.all(),
|
||||
required=False,
|
||||
label='Bridged interface',
|
||||
label=_('Bridged interface'),
|
||||
query_params={
|
||||
'virtual_machine_id': '$virtual_machine',
|
||||
}
|
||||
@ -313,12 +314,12 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
||||
vlan_group = DynamicModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
label='VLAN group'
|
||||
label=_('VLAN group')
|
||||
)
|
||||
untagged_vlan = DynamicModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
label='Untagged VLAN',
|
||||
label=_('Untagged VLAN'),
|
||||
query_params={
|
||||
'group_id': '$vlan_group',
|
||||
'available_on_virtualmachine': '$virtual_machine',
|
||||
@ -327,7 +328,7 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
||||
tagged_vlans = DynamicModelMultipleChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
label='Tagged VLANs',
|
||||
label=_('Tagged VLANs'),
|
||||
query_params={
|
||||
'group_id': '$vlan_group',
|
||||
'available_on_virtualmachine': '$virtual_machine',
|
||||
@ -336,7 +337,7 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
|
||||
vrf = DynamicModelChoiceField(
|
||||
queryset=VRF.objects.all(),
|
||||
required=False,
|
||||
label='VRF'
|
||||
label=_('VRF')
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.choices import LinkStatusChoices
|
||||
from ipam.models import VLAN
|
||||
@ -45,12 +46,12 @@ class WirelessLANBulkEditForm(NetBoxModelBulkEditForm):
|
||||
vlan = DynamicModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
label='VLAN'
|
||||
label=_('VLAN')
|
||||
)
|
||||
ssid = forms.CharField(
|
||||
max_length=SSID_MAX_LENGTH,
|
||||
required=False,
|
||||
label='SSID'
|
||||
label=_('SSID')
|
||||
)
|
||||
tenant = DynamicModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
@ -66,7 +67,7 @@ class WirelessLANBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
auth_psk = forms.CharField(
|
||||
required=False,
|
||||
label='Pre-shared key'
|
||||
label=_('Pre-shared key')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
@ -91,7 +92,7 @@ class WirelessLinkBulkEditForm(NetBoxModelBulkEditForm):
|
||||
ssid = forms.CharField(
|
||||
max_length=SSID_MAX_LENGTH,
|
||||
required=False,
|
||||
label='SSID'
|
||||
label=_('SSID')
|
||||
)
|
||||
status = forms.ChoiceField(
|
||||
choices=add_blank_choice(LinkStatusChoices),
|
||||
@ -111,7 +112,7 @@ class WirelessLinkBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
auth_psk = forms.CharField(
|
||||
required=False,
|
||||
label='Pre-shared key'
|
||||
label=_('Pre-shared key')
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
|
@ -1,3 +1,4 @@
|
||||
from django.utils.translation import gettext as _
|
||||
from dcim.choices import LinkStatusChoices
|
||||
from dcim.models import Interface
|
||||
from ipam.models import VLAN
|
||||
@ -19,7 +20,7 @@ class WirelessLANGroupCSVForm(NetBoxModelCSVForm):
|
||||
queryset=WirelessLANGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Parent group'
|
||||
help_text=_('Parent group')
|
||||
)
|
||||
slug = SlugField()
|
||||
|
||||
@ -33,7 +34,7 @@ class WirelessLANCSVForm(NetBoxModelCSVForm):
|
||||
queryset=WirelessLANGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned group'
|
||||
help_text=_('Assigned group')
|
||||
)
|
||||
status = CSVChoiceField(
|
||||
choices=WirelessLANStatusChoices,
|
||||
@ -43,23 +44,23 @@ class WirelessLANCSVForm(NetBoxModelCSVForm):
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Bridged VLAN'
|
||||
help_text=_('Bridged VLAN')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
auth_type = CSVChoiceField(
|
||||
choices=WirelessAuthTypeChoices,
|
||||
required=False,
|
||||
help_text='Authentication type'
|
||||
help_text=_('Authentication type')
|
||||
)
|
||||
auth_cipher = CSVChoiceField(
|
||||
choices=WirelessAuthCipherChoices,
|
||||
required=False,
|
||||
help_text='Authentication cipher'
|
||||
help_text=_('Authentication cipher')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@ -73,7 +74,7 @@ class WirelessLANCSVForm(NetBoxModelCSVForm):
|
||||
class WirelessLinkCSVForm(NetBoxModelCSVForm):
|
||||
status = CSVChoiceField(
|
||||
choices=LinkStatusChoices,
|
||||
help_text='Connection status'
|
||||
help_text=_('Connection status')
|
||||
)
|
||||
interface_a = CSVModelChoiceField(
|
||||
queryset=Interface.objects.all()
|
||||
@ -85,17 +86,17 @@ class WirelessLinkCSVForm(NetBoxModelCSVForm):
|
||||
queryset=Tenant.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text='Assigned tenant'
|
||||
help_text=_('Assigned tenant')
|
||||
)
|
||||
auth_type = CSVChoiceField(
|
||||
choices=WirelessAuthTypeChoices,
|
||||
required=False,
|
||||
help_text='Authentication type'
|
||||
help_text=_('Authentication type')
|
||||
)
|
||||
auth_cipher = CSVChoiceField(
|
||||
choices=WirelessAuthCipherChoices,
|
||||
required=False,
|
||||
help_text='Authentication cipher'
|
||||
help_text=_('Authentication cipher')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -35,7 +35,7 @@ class WirelessLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
)
|
||||
ssid = forms.CharField(
|
||||
required=False,
|
||||
label='SSID'
|
||||
label=_('SSID')
|
||||
)
|
||||
group_id = DynamicModelMultipleChoiceField(
|
||||
queryset=WirelessLANGroup.objects.all(),
|
||||
@ -74,7 +74,7 @@ class WirelessLinkFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
)
|
||||
ssid = forms.CharField(
|
||||
required=False,
|
||||
label='SSID'
|
||||
label=_('SSID')
|
||||
)
|
||||
status = forms.ChoiceField(
|
||||
required=False,
|
||||
|
@ -1,3 +1,4 @@
|
||||
from django.utils.translation import gettext as _
|
||||
from dcim.models import Device, Interface, Location, Region, Site, SiteGroup
|
||||
from ipam.models import VLAN, VLANGroup
|
||||
from netbox.forms import NetBoxModelForm
|
||||
@ -63,7 +64,7 @@ class WirelessLANForm(TenancyForm, NetBoxModelForm):
|
||||
vlan_group = DynamicModelChoiceField(
|
||||
queryset=VLANGroup.objects.all(),
|
||||
required=False,
|
||||
label='VLAN group',
|
||||
label=_('VLAN group'),
|
||||
null_option='None',
|
||||
query_params={
|
||||
'site': '$site'
|
||||
@ -75,7 +76,7 @@ class WirelessLANForm(TenancyForm, NetBoxModelForm):
|
||||
vlan = DynamicModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
label='VLAN',
|
||||
label=_('VLAN'),
|
||||
query_params={
|
||||
'site_id': '$site',
|
||||
'group_id': '$vlan_group',
|
||||
@ -107,7 +108,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
|
||||
site_a = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False,
|
||||
label='Site',
|
||||
label=_('Site'),
|
||||
initial_params={
|
||||
'devices': '$device_a',
|
||||
}
|
||||
@ -118,7 +119,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
|
||||
'site_id': '$site_a',
|
||||
},
|
||||
required=False,
|
||||
label='Location',
|
||||
label=_('Location'),
|
||||
initial_params={
|
||||
'devices': '$device_a',
|
||||
}
|
||||
@ -130,7 +131,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
|
||||
'location_id': '$location_a',
|
||||
},
|
||||
required=False,
|
||||
label='Device',
|
||||
label=_('Device'),
|
||||
initial_params={
|
||||
'interfaces': '$interface_a'
|
||||
}
|
||||
@ -142,12 +143,12 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
|
||||
'device_id': '$device_a',
|
||||
},
|
||||
disabled_indicator='_occupied',
|
||||
label='Interface'
|
||||
label=_('Interface')
|
||||
)
|
||||
site_b = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False,
|
||||
label='Site',
|
||||
label=_('Site'),
|
||||
initial_params={
|
||||
'devices': '$device_b',
|
||||
}
|
||||
@ -158,7 +159,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
|
||||
'site_id': '$site_b',
|
||||
},
|
||||
required=False,
|
||||
label='Location',
|
||||
label=_('Location'),
|
||||
initial_params={
|
||||
'devices': '$device_b',
|
||||
}
|
||||
@ -170,7 +171,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
|
||||
'location_id': '$location_b',
|
||||
},
|
||||
required=False,
|
||||
label='Device',
|
||||
label=_('Device'),
|
||||
initial_params={
|
||||
'interfaces': '$interface_b'
|
||||
}
|
||||
@ -182,7 +183,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
|
||||
'device_id': '$device_b',
|
||||
},
|
||||
disabled_indicator='_occupied',
|
||||
label='Interface'
|
||||
label=_('Interface')
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user