10300 initial translation support use gettext

This commit is contained in:
Arthur 2022-11-03 11:58:26 -07:00 committed by Jeremy Stretch
parent 2cc2d2cc37
commit 6eba5d4d96
67 changed files with 1192 additions and 1134 deletions

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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(),

View File

@ -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,

View File

@ -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

View File

@ -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.)')
)

View File

@ -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

View File

@ -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:

View File

@ -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):

View File

@ -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',

View File

@ -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(),
)

View File

@ -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:

View File

@ -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:

View File

@ -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()

View File

@ -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()

View File

@ -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')

View File

@ -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,

View File

@ -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.')
)
)

View File

@ -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

View File

@ -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:

View File

@ -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')

View File

@ -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>)')),
}

View File

@ -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,

View File

@ -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,
}

View File

@ -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>.'),
}

View File

@ -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"),
)

View File

@ -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):

View File

@ -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()

View File

@ -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. "
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)."
"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 '
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>.'
'<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' "
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."
"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(

View File

@ -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

View File

@ -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()

View File

@ -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')
)

View File

@ -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,

View File

@ -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:

View File

@ -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)

View File

@ -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:

View File

@ -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()

View File

@ -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:

View File

@ -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',

View File

@ -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")
),
)

View File

@ -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()

View File

@ -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(

View File

@ -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):

View File

@ -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
)

View File

@ -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'),

View File

@ -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)'),
)

View File

@ -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:

View File

@ -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 '
'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.'
'operation.')
}
labels = {
'actions': 'Additional actions'

View File

@ -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:

View File

@ -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:

View File

@ -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()

View File

@ -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()))

View File

@ -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

View File

@ -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'

View File

@ -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):

View File

@ -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:

View File

@ -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):

View File

@ -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

View File

@ -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:

View File

@ -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
)

View File

@ -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 = (

View File

@ -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,

View File

@ -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:

View File

@ -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,

View File

@ -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()