mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-25 08:46:10 -06:00
13132 add gettext_lazy to models
This commit is contained in:
parent
90c9e71682
commit
d051494cef
@ -1,3 +1,4 @@
|
|||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
|
|
||||||
from circuits.models import *
|
from circuits.models import *
|
||||||
@ -53,19 +54,19 @@ class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
|||||||
)
|
)
|
||||||
provider_account = tables.Column(
|
provider_account = tables.Column(
|
||||||
linkify=True,
|
linkify=True,
|
||||||
verbose_name='Account'
|
verbose_name=_('Account')
|
||||||
)
|
)
|
||||||
status = columns.ChoiceFieldColumn()
|
status = columns.ChoiceFieldColumn()
|
||||||
termination_a = tables.TemplateColumn(
|
termination_a = tables.TemplateColumn(
|
||||||
template_code=CIRCUITTERMINATION_LINK,
|
template_code=CIRCUITTERMINATION_LINK,
|
||||||
verbose_name='Side A'
|
verbose_name=_('Side A')
|
||||||
)
|
)
|
||||||
termination_z = tables.TemplateColumn(
|
termination_z = tables.TemplateColumn(
|
||||||
template_code=CIRCUITTERMINATION_LINK,
|
template_code=CIRCUITTERMINATION_LINK,
|
||||||
verbose_name='Side Z'
|
verbose_name=_('Side Z')
|
||||||
)
|
)
|
||||||
commit_rate = CommitRateColumn(
|
commit_rate = CommitRateColumn(
|
||||||
verbose_name='Commit Rate'
|
verbose_name=_('Commit Rate')
|
||||||
)
|
)
|
||||||
comments = columns.MarkdownColumn()
|
comments = columns.MarkdownColumn()
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
|
@ -2,6 +2,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from netbox.models import ChangeLoggedModel, NestedGroupModel, OrganizationalModel, PrimaryModel
|
from netbox.models import ChangeLoggedModel, NestedGroupModel, OrganizationalModel, PrimaryModel
|
||||||
from tenancy.choices import *
|
from tenancy.choices import *
|
||||||
@ -51,24 +52,30 @@ class Contact(PrimaryModel):
|
|||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
|
verbose_name=_('name'),
|
||||||
max_length=100
|
max_length=100
|
||||||
)
|
)
|
||||||
title = models.CharField(
|
title = models.CharField(
|
||||||
|
verbose_name=_('title'),
|
||||||
max_length=100,
|
max_length=100,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
phone = models.CharField(
|
phone = models.CharField(
|
||||||
|
verbose_name=_('phone'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
email = models.EmailField(
|
email = models.EmailField(
|
||||||
|
verbose_name=_('email'),
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
address = models.CharField(
|
address = models.CharField(
|
||||||
|
verbose_name=_('address'),
|
||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
link = models.URLField(
|
link = models.URLField(
|
||||||
|
verbose_name=_('link'),
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -113,6 +120,7 @@ class ContactAssignment(ChangeLoggedModel):
|
|||||||
related_name='assignments'
|
related_name='assignments'
|
||||||
)
|
)
|
||||||
priority = models.CharField(
|
priority = models.CharField(
|
||||||
|
verbose_name=_('priority'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=ContactPriorityChoices,
|
choices=ContactPriorityChoices,
|
||||||
blank=True
|
blank=True
|
||||||
|
@ -2,6 +2,7 @@ from django.contrib.contenttypes.fields import GenericRelation
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from netbox.models import NestedGroupModel, PrimaryModel
|
from netbox.models import NestedGroupModel, PrimaryModel
|
||||||
|
|
||||||
@ -16,10 +17,12 @@ class TenantGroup(NestedGroupModel):
|
|||||||
An arbitrary collection of Tenants.
|
An arbitrary collection of Tenants.
|
||||||
"""
|
"""
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
|
verbose_name=_('name'),
|
||||||
max_length=100,
|
max_length=100,
|
||||||
unique=True
|
unique=True
|
||||||
)
|
)
|
||||||
slug = models.SlugField(
|
slug = models.SlugField(
|
||||||
|
verbose_name=_('slug'),
|
||||||
max_length=100,
|
max_length=100,
|
||||||
unique=True
|
unique=True
|
||||||
)
|
)
|
||||||
@ -37,9 +40,11 @@ class Tenant(PrimaryModel):
|
|||||||
department.
|
department.
|
||||||
"""
|
"""
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
|
verbose_name=_('name'),
|
||||||
max_length=100
|
max_length=100
|
||||||
)
|
)
|
||||||
slug = models.SlugField(
|
slug = models.SlugField(
|
||||||
|
verbose_name=_('slug'),
|
||||||
max_length=100
|
max_length=100
|
||||||
)
|
)
|
||||||
group = models.ForeignKey(
|
group = models.ForeignKey(
|
||||||
@ -65,7 +70,7 @@ class Tenant(PrimaryModel):
|
|||||||
models.UniqueConstraint(
|
models.UniqueConstraint(
|
||||||
fields=('group', 'name'),
|
fields=('group', 'name'),
|
||||||
name='%(app_label)s_%(class)s_unique_group_name',
|
name='%(app_label)s_%(class)s_unique_group_name',
|
||||||
violation_error_message="Tenant name must be unique per group."
|
violation_error_message=_("Tenant name must be unique per group.")
|
||||||
),
|
),
|
||||||
models.UniqueConstraint(
|
models.UniqueConstraint(
|
||||||
fields=('name',),
|
fields=('name',),
|
||||||
@ -75,7 +80,7 @@ class Tenant(PrimaryModel):
|
|||||||
models.UniqueConstraint(
|
models.UniqueConstraint(
|
||||||
fields=('group', 'slug'),
|
fields=('group', 'slug'),
|
||||||
name='%(app_label)s_%(class)s_unique_group_slug',
|
name='%(app_label)s_%(class)s_unique_group_slug',
|
||||||
violation_error_message="Tenant slug must be unique per group."
|
violation_error_message=_("Tenant slug must be unique per group.")
|
||||||
),
|
),
|
||||||
models.UniqueConstraint(
|
models.UniqueConstraint(
|
||||||
fields=('slug',),
|
fields=('slug',),
|
||||||
|
@ -11,7 +11,7 @@ from django.db.models.signals import post_save
|
|||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from netaddr import IPNetwork
|
from netaddr import IPNetwork
|
||||||
|
|
||||||
from ipam.fields import IPNetworkField
|
from ipam.fields import IPNetworkField
|
||||||
@ -40,7 +40,7 @@ class AdminGroup(Group):
|
|||||||
Proxy contrib.auth.models.Group for the admin UI
|
Proxy contrib.auth.models.Group for the admin UI
|
||||||
"""
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = 'Group'
|
verbose_name = _('Group')
|
||||||
proxy = True
|
proxy = True
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ class AdminUser(User):
|
|||||||
Proxy contrib.auth.models.User for the admin UI
|
Proxy contrib.auth.models.User for the admin UI
|
||||||
"""
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = 'User'
|
verbose_name = _('User')
|
||||||
proxy = True
|
proxy = True
|
||||||
|
|
||||||
|
|
||||||
@ -105,12 +105,13 @@ class UserConfig(models.Model):
|
|||||||
related_name='config'
|
related_name='config'
|
||||||
)
|
)
|
||||||
data = models.JSONField(
|
data = models.JSONField(
|
||||||
|
verbose_name=_('data'),
|
||||||
default=dict
|
default=dict
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['user']
|
ordering = ['user']
|
||||||
verbose_name = verbose_name_plural = 'User Preferences'
|
verbose_name = verbose_name_plural = _('User Preferences')
|
||||||
|
|
||||||
def get(self, path, default=None):
|
def get(self, path, default=None):
|
||||||
"""
|
"""
|
||||||
@ -176,7 +177,7 @@ class UserConfig(models.Model):
|
|||||||
d = d[key]
|
d = d[key]
|
||||||
elif key in d:
|
elif key in d:
|
||||||
err_path = '.'.join(path.split('.')[:i + 1])
|
err_path = '.'.join(path.split('.')[:i + 1])
|
||||||
raise TypeError(f"Key '{err_path}' is a leaf node; cannot assign new keys")
|
raise TypeError(_("Key '{err_path}' is a leaf node; cannot assign new keys").format(err_path=err_path))
|
||||||
else:
|
else:
|
||||||
d = d.setdefault(key, {})
|
d = d.setdefault(key, {})
|
||||||
|
|
||||||
@ -186,7 +187,7 @@ class UserConfig(models.Model):
|
|||||||
if type(value) is dict:
|
if type(value) is dict:
|
||||||
d[key].update(value)
|
d[key].update(value)
|
||||||
else:
|
else:
|
||||||
raise TypeError(f"Key '{path}' is a dictionary; cannot assign a non-dictionary value")
|
raise TypeError(_("Key '{path}' is a dictionary; cannot assign a non-dictionary value").format(path=path))
|
||||||
else:
|
else:
|
||||||
d[key] = value
|
d[key] = value
|
||||||
|
|
||||||
@ -246,26 +247,32 @@ class Token(models.Model):
|
|||||||
related_name='tokens'
|
related_name='tokens'
|
||||||
)
|
)
|
||||||
created = models.DateTimeField(
|
created = models.DateTimeField(
|
||||||
|
verbose_name=_('created'),
|
||||||
auto_now_add=True
|
auto_now_add=True
|
||||||
)
|
)
|
||||||
expires = models.DateTimeField(
|
expires = models.DateTimeField(
|
||||||
|
verbose_name=_('expires'),
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
last_used = models.DateTimeField(
|
last_used = models.DateTimeField(
|
||||||
|
verbose_name=_('last used'),
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
key = models.CharField(
|
key = models.CharField(
|
||||||
|
verbose_name=_('key'),
|
||||||
max_length=40,
|
max_length=40,
|
||||||
unique=True,
|
unique=True,
|
||||||
validators=[MinLengthValidator(40)]
|
validators=[MinLengthValidator(40)]
|
||||||
)
|
)
|
||||||
write_enabled = models.BooleanField(
|
write_enabled = models.BooleanField(
|
||||||
|
verbose_name=_('write enabled'),
|
||||||
default=True,
|
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(
|
description = models.CharField(
|
||||||
|
verbose_name=_('description'),
|
||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
@ -273,7 +280,7 @@ class Token(models.Model):
|
|||||||
base_field=IPNetworkField(),
|
base_field=IPNetworkField(),
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
verbose_name='Allowed IPs',
|
verbose_name=_('Allowed IPs'),
|
||||||
help_text=_(
|
help_text=_(
|
||||||
'Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
|
'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"'
|
'Ex: "10.1.1.0/24, 192.168.10.16/32, 2001:DB8:1::/64"'
|
||||||
@ -344,13 +351,16 @@ class ObjectPermission(models.Model):
|
|||||||
identified by ORM query parameters.
|
identified by ORM query parameters.
|
||||||
"""
|
"""
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
|
verbose_name=_('name'),
|
||||||
max_length=100
|
max_length=100
|
||||||
)
|
)
|
||||||
description = models.CharField(
|
description = models.CharField(
|
||||||
|
verbose_name=_('description'),
|
||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
enabled = models.BooleanField(
|
enabled = models.BooleanField(
|
||||||
|
verbose_name=_('enabled'),
|
||||||
default=True
|
default=True
|
||||||
)
|
)
|
||||||
object_types = models.ManyToManyField(
|
object_types = models.ManyToManyField(
|
||||||
@ -382,7 +392,7 @@ class ObjectPermission(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['name']
|
ordering = ['name']
|
||||||
verbose_name = "permission"
|
verbose_name = _("permission")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -2,6 +2,7 @@ from django.contrib.contenttypes.fields import GenericRelation
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from dcim.models import Device
|
from dcim.models import Device
|
||||||
from netbox.models import OrganizationalModel, PrimaryModel
|
from netbox.models import OrganizationalModel, PrimaryModel
|
||||||
@ -46,9 +47,11 @@ class Cluster(PrimaryModel):
|
|||||||
A cluster of VirtualMachines. Each Cluster may optionally be associated with one or more Devices.
|
A cluster of VirtualMachines. Each Cluster may optionally be associated with one or more Devices.
|
||||||
"""
|
"""
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
|
verbose_name=_('name'),
|
||||||
max_length=100
|
max_length=100
|
||||||
)
|
)
|
||||||
type = models.ForeignKey(
|
type = models.ForeignKey(
|
||||||
|
verbose_name=_('type'),
|
||||||
to=ClusterType,
|
to=ClusterType,
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='clusters'
|
related_name='clusters'
|
||||||
@ -61,6 +64,7 @@ class Cluster(PrimaryModel):
|
|||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
status = models.CharField(
|
status = models.CharField(
|
||||||
|
verbose_name=_('status'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=ClusterStatusChoices,
|
choices=ClusterStatusChoices,
|
||||||
default=ClusterStatusChoices.STATUS_ACTIVE
|
default=ClusterStatusChoices.STATUS_ACTIVE
|
||||||
@ -128,7 +132,7 @@ class Cluster(PrimaryModel):
|
|||||||
nonsite_devices = Device.objects.filter(cluster=self).exclude(site=self.site).count()
|
nonsite_devices = Device.objects.filter(cluster=self).exclude(site=self.site).count()
|
||||||
if nonsite_devices:
|
if nonsite_devices:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'site': "{} devices are assigned as hosts for this cluster but are not in site {}".format(
|
'site': _("{} devices are assigned as hosts for this cluster but are not in site {}").format(
|
||||||
nonsite_devices, self.site
|
nonsite_devices, self.site
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -5,6 +5,7 @@ from django.db import models
|
|||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.db.models.functions import Lower
|
from django.db.models.functions import Lower
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from dcim.models import BaseInterface
|
from dcim.models import BaseInterface
|
||||||
from extras.models import ConfigContextModel
|
from extras.models import ConfigContextModel
|
||||||
@ -63,6 +64,7 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
|
verbose_name=_('name'),
|
||||||
max_length=64
|
max_length=64
|
||||||
)
|
)
|
||||||
_name = NaturalOrderingField(
|
_name = NaturalOrderingField(
|
||||||
@ -74,7 +76,7 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=VirtualMachineStatusChoices,
|
choices=VirtualMachineStatusChoices,
|
||||||
default=VirtualMachineStatusChoices.STATUS_ACTIVE,
|
default=VirtualMachineStatusChoices.STATUS_ACTIVE,
|
||||||
verbose_name='Status'
|
verbose_name=_('Status')
|
||||||
)
|
)
|
||||||
role = models.ForeignKey(
|
role = models.ForeignKey(
|
||||||
to='dcim.DeviceRole',
|
to='dcim.DeviceRole',
|
||||||
@ -113,12 +115,12 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
memory = models.PositiveIntegerField(
|
memory = models.PositiveIntegerField(
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
verbose_name='Memory (MB)'
|
verbose_name=_('Memory (MB)')
|
||||||
)
|
)
|
||||||
disk = models.PositiveIntegerField(
|
disk = models.PositiveIntegerField(
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
verbose_name='Disk (GB)'
|
verbose_name=_('Disk (GB)')
|
||||||
)
|
)
|
||||||
|
|
||||||
# Counter fields
|
# Counter fields
|
||||||
@ -152,7 +154,7 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
Lower('name'), 'cluster',
|
Lower('name'), 'cluster',
|
||||||
name='%(app_label)s_%(class)s_unique_name_cluster',
|
name='%(app_label)s_%(class)s_unique_name_cluster',
|
||||||
condition=Q(tenant__isnull=True),
|
condition=Q(tenant__isnull=True),
|
||||||
violation_error_message="Virtual machine name must be unique per cluster."
|
violation_error_message=_("Virtual machine name must be unique per cluster.")
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -168,23 +170,23 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
# Must be assigned to a site and/or cluster
|
# Must be assigned to a site and/or cluster
|
||||||
if not self.site and not self.cluster:
|
if not self.site and not self.cluster:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'cluster': f'A virtual machine must be assigned to a site and/or cluster.'
|
'cluster': _('A virtual machine must be assigned to a site and/or cluster.')
|
||||||
})
|
})
|
||||||
|
|
||||||
# Validate site for cluster & device
|
# Validate site for cluster & device
|
||||||
if self.cluster and self.site and self.cluster.site != self.site:
|
if self.cluster and self.site and self.cluster.site != self.site:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'cluster': f'The selected cluster ({self.cluster}) is not assigned to this site ({self.site}).'
|
'cluster': _('The selected cluster ({cluster}) is not assigned to this site ({site}).').format(cluster=self.cluster, site=self.site)
|
||||||
})
|
})
|
||||||
|
|
||||||
# Validate assigned cluster device
|
# Validate assigned cluster device
|
||||||
if self.device and not self.cluster:
|
if self.device and not self.cluster:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'device': f'Must specify a cluster when assigning a host device.'
|
'device': _('Must specify a cluster when assigning a host device.')
|
||||||
})
|
})
|
||||||
if self.device and self.device not in self.cluster.devices.all():
|
if self.device and self.device not in self.cluster.devices.all():
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'device': f'The selected device ({self.device}) is not assigned to this cluster ({self.cluster}).'
|
'device': _('The selected device ({device}) is not assigned to this cluster ({cluster}).').format(device=self.device, cluster=self.cluster)
|
||||||
})
|
})
|
||||||
|
|
||||||
# Validate primary IP addresses
|
# Validate primary IP addresses
|
||||||
@ -195,7 +197,8 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
if ip is not None:
|
if ip is not None:
|
||||||
if ip.address.version != family:
|
if ip.address.version != family:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
field: f"Must be an IPv{family} address. ({ip} is an IPv{ip.address.version} address.)",
|
field: _("Must be an IPv{family} address. ({ip} is an IPv{version} address.)").format(
|
||||||
|
family=family, ip=ip, version=ip.address.version),
|
||||||
})
|
})
|
||||||
if ip.assigned_object in interfaces:
|
if ip.assigned_object in interfaces:
|
||||||
pass
|
pass
|
||||||
@ -203,7 +206,7 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
field: f"The specified IP address ({ip}) is not assigned to this VM.",
|
field: _("The specified IP address ({ip}) is not assigned to this VM.").format(ip=ip),
|
||||||
})
|
})
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
@ -236,6 +239,7 @@ class VMInterface(NetBoxModel, BaseInterface, TrackingModelMixin):
|
|||||||
related_name='interfaces'
|
related_name='interfaces'
|
||||||
)
|
)
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
|
verbose_name=_('name'),
|
||||||
max_length=64
|
max_length=64
|
||||||
)
|
)
|
||||||
_name = NaturalOrderingField(
|
_name = NaturalOrderingField(
|
||||||
@ -245,6 +249,7 @@ class VMInterface(NetBoxModel, BaseInterface, TrackingModelMixin):
|
|||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
description = models.CharField(
|
description = models.CharField(
|
||||||
|
verbose_name=_('description'),
|
||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
@ -254,13 +259,13 @@ class VMInterface(NetBoxModel, BaseInterface, TrackingModelMixin):
|
|||||||
related_name='vminterfaces_as_untagged',
|
related_name='vminterfaces_as_untagged',
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name='Untagged VLAN'
|
verbose_name=_('Untagged VLAN')
|
||||||
)
|
)
|
||||||
tagged_vlans = models.ManyToManyField(
|
tagged_vlans = models.ManyToManyField(
|
||||||
to='ipam.VLAN',
|
to='ipam.VLAN',
|
||||||
related_name='vminterfaces_as_tagged',
|
related_name='vminterfaces_as_tagged',
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name='Tagged VLANs'
|
verbose_name=_('Tagged VLANs')
|
||||||
)
|
)
|
||||||
ip_addresses = GenericRelation(
|
ip_addresses = GenericRelation(
|
||||||
to='ipam.IPAddress',
|
to='ipam.IPAddress',
|
||||||
@ -274,7 +279,7 @@ class VMInterface(NetBoxModel, BaseInterface, TrackingModelMixin):
|
|||||||
related_name='vminterfaces',
|
related_name='vminterfaces',
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name='VRF'
|
verbose_name=_('VRF')
|
||||||
)
|
)
|
||||||
fhrp_group_assignments = GenericRelation(
|
fhrp_group_assignments = GenericRelation(
|
||||||
to='ipam.FHRPGroupAssignment',
|
to='ipam.FHRPGroupAssignment',
|
||||||
@ -312,26 +317,26 @@ class VMInterface(NetBoxModel, BaseInterface, TrackingModelMixin):
|
|||||||
|
|
||||||
# An interface cannot be its own parent
|
# An interface cannot be its own parent
|
||||||
if self.pk and self.parent_id == self.pk:
|
if self.pk and self.parent_id == self.pk:
|
||||||
raise ValidationError({'parent': "An interface cannot be its own parent."})
|
raise ValidationError({'parent': _("An interface cannot be its own parent.")})
|
||||||
|
|
||||||
# An interface's parent must belong to the same virtual machine
|
# An interface's parent must belong to the same virtual machine
|
||||||
if self.parent and self.parent.virtual_machine != self.virtual_machine:
|
if self.parent and self.parent.virtual_machine != self.virtual_machine:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'parent': f"The selected parent interface ({self.parent}) belongs to a different virtual machine "
|
'parent': _("The selected parent interface ({parent}) belongs to a different virtual machine "
|
||||||
f"({self.parent.virtual_machine})."
|
"({virtual_machine}).").format(parent=self.parent, virtual_machine=self.parent.virtual_machine)
|
||||||
})
|
})
|
||||||
|
|
||||||
# Bridge validation
|
# Bridge validation
|
||||||
|
|
||||||
# An interface cannot be bridged to itself
|
# An interface cannot be bridged to itself
|
||||||
if self.pk and self.bridge_id == self.pk:
|
if self.pk and self.bridge_id == self.pk:
|
||||||
raise ValidationError({'bridge': "An interface cannot be bridged to itself."})
|
raise ValidationError({'bridge': _("An interface cannot be bridged to itself.")})
|
||||||
|
|
||||||
# A bridged interface belong to the same virtual machine
|
# A bridged interface belong to the same virtual machine
|
||||||
if self.bridge and self.bridge.virtual_machine != self.virtual_machine:
|
if self.bridge and self.bridge.virtual_machine != self.virtual_machine:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'bridge': f"The selected bridge interface ({self.bridge}) belongs to a different virtual machine "
|
'bridge': _("The selected bridge interface ({bridge}) belongs to a different virtual machine "
|
||||||
f"({self.bridge.virtual_machine})."
|
"({virtual_machine}).").format(bridge=self.bridge, virtual_machine=self.bridge.virtual_machine)
|
||||||
})
|
})
|
||||||
|
|
||||||
# VLAN validation
|
# VLAN validation
|
||||||
@ -339,8 +344,8 @@ class VMInterface(NetBoxModel, BaseInterface, TrackingModelMixin):
|
|||||||
# Validate untagged VLAN
|
# Validate untagged VLAN
|
||||||
if self.untagged_vlan and self.untagged_vlan.site not in [self.virtual_machine.site, None]:
|
if self.untagged_vlan and self.untagged_vlan.site not in [self.virtual_machine.site, None]:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'untagged_vlan': f"The untagged VLAN ({self.untagged_vlan}) must belong to the same site as the "
|
'untagged_vlan': _("The untagged VLAN ({untagged_vlan}) must belong to the same site as the "
|
||||||
f"interface's parent virtual machine, or it must be global."
|
"interface's parent virtual machine, or it must be global.").format(untagged_vlan=self.untagged_vlan)
|
||||||
})
|
})
|
||||||
|
|
||||||
def to_objectchange(self, action):
|
def to_objectchange(self, action):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from mptt.models import MPTTModel
|
from mptt.models import MPTTModel
|
||||||
|
|
||||||
from dcim.choices import LinkStatusChoices
|
from dcim.choices import LinkStatusChoices
|
||||||
@ -24,9 +25,10 @@ class WirelessAuthenticationBase(models.Model):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=WirelessAuthTypeChoices,
|
choices=WirelessAuthTypeChoices,
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name="Auth Type",
|
verbose_name=_("Auth Type"),
|
||||||
)
|
)
|
||||||
auth_cipher = models.CharField(
|
auth_cipher = models.CharField(
|
||||||
|
verbose_name=_('auth cipher'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=WirelessAuthCipherChoices,
|
choices=WirelessAuthCipherChoices,
|
||||||
blank=True
|
blank=True
|
||||||
@ -34,7 +36,7 @@ class WirelessAuthenticationBase(models.Model):
|
|||||||
auth_psk = models.CharField(
|
auth_psk = models.CharField(
|
||||||
max_length=PSK_MAX_LENGTH,
|
max_length=PSK_MAX_LENGTH,
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name='Pre-shared key'
|
verbose_name=_('Pre-shared key')
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -46,10 +48,12 @@ class WirelessLANGroup(NestedGroupModel):
|
|||||||
A nested grouping of WirelessLANs
|
A nested grouping of WirelessLANs
|
||||||
"""
|
"""
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
|
verbose_name=_('name'),
|
||||||
max_length=100,
|
max_length=100,
|
||||||
unique=True
|
unique=True
|
||||||
)
|
)
|
||||||
slug = models.SlugField(
|
slug = models.SlugField(
|
||||||
|
verbose_name=_('slug'),
|
||||||
max_length=100,
|
max_length=100,
|
||||||
unique=True
|
unique=True
|
||||||
)
|
)
|
||||||
@ -74,7 +78,7 @@ class WirelessLAN(WirelessAuthenticationBase, PrimaryModel):
|
|||||||
"""
|
"""
|
||||||
ssid = models.CharField(
|
ssid = models.CharField(
|
||||||
max_length=SSID_MAX_LENGTH,
|
max_length=SSID_MAX_LENGTH,
|
||||||
verbose_name='SSID'
|
verbose_name=_('SSID')
|
||||||
)
|
)
|
||||||
group = models.ForeignKey(
|
group = models.ForeignKey(
|
||||||
to='wireless.WirelessLANGroup',
|
to='wireless.WirelessLANGroup',
|
||||||
@ -93,7 +97,7 @@ class WirelessLAN(WirelessAuthenticationBase, PrimaryModel):
|
|||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
verbose_name='VLAN'
|
verbose_name=_('VLAN')
|
||||||
)
|
)
|
||||||
tenant = models.ForeignKey(
|
tenant = models.ForeignKey(
|
||||||
to='tenancy.Tenant',
|
to='tenancy.Tenant',
|
||||||
@ -134,21 +138,22 @@ class WirelessLink(WirelessAuthenticationBase, PrimaryModel):
|
|||||||
limit_choices_to=get_wireless_interface_types,
|
limit_choices_to=get_wireless_interface_types,
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='+',
|
related_name='+',
|
||||||
verbose_name="Interface A",
|
verbose_name=_('Interface A'),
|
||||||
)
|
)
|
||||||
interface_b = models.ForeignKey(
|
interface_b = models.ForeignKey(
|
||||||
to='dcim.Interface',
|
to='dcim.Interface',
|
||||||
limit_choices_to=get_wireless_interface_types,
|
limit_choices_to=get_wireless_interface_types,
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='+',
|
related_name='+',
|
||||||
verbose_name="Interface B",
|
verbose_name=_('Interface B'),
|
||||||
)
|
)
|
||||||
ssid = models.CharField(
|
ssid = models.CharField(
|
||||||
max_length=SSID_MAX_LENGTH,
|
max_length=SSID_MAX_LENGTH,
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name='SSID'
|
verbose_name=_('SSID')
|
||||||
)
|
)
|
||||||
status = models.CharField(
|
status = models.CharField(
|
||||||
|
verbose_name=_('status'),
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=LinkStatusChoices,
|
choices=LinkStatusChoices,
|
||||||
default=LinkStatusChoices.STATUS_CONNECTED
|
default=LinkStatusChoices.STATUS_CONNECTED
|
||||||
@ -203,11 +208,11 @@ class WirelessLink(WirelessAuthenticationBase, PrimaryModel):
|
|||||||
# Validate interface types
|
# Validate interface types
|
||||||
if self.interface_a.type not in WIRELESS_IFACE_TYPES:
|
if self.interface_a.type not in WIRELESS_IFACE_TYPES:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'interface_a': f"{self.interface_a.get_type_display()} is not a wireless interface."
|
'interface_a': _("{type_display} is not a wireless interface.").format(type_display=self.interface_a.get_type_display())
|
||||||
})
|
})
|
||||||
if self.interface_b.type not in WIRELESS_IFACE_TYPES:
|
if self.interface_b.type not in WIRELESS_IFACE_TYPES:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
'interface_a': f"{self.interface_b.get_type_display()} is not a wireless interface."
|
'interface_a': _("{type_display} is not a wireless interface.").format(type_display=self.interface_b.get_type_display())
|
||||||
})
|
})
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
Loading…
Reference in New Issue
Block a user