1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #13352: Translation support for model verbose names (#13354)

* Update verbose_name & verbose_name_plural Meta attributes on all models

* Alter makemigrations to ignore verbose_name & verbose_name_plural changes
This commit is contained in:
Jeremy Stretch
2023-08-03 10:41:10 -04:00
committed by GitHub
parent 24ffaf09d4
commit caedc8dbe3
36 changed files with 288 additions and 28 deletions

View File

@ -25,6 +25,11 @@ class CircuitType(OrganizationalModel):
def get_absolute_url(self):
return reverse('circuits:circuittype', args=[self.pk])
class Meta:
ordering = ('name',)
verbose_name = _('circuit type')
verbose_name_plural = _('circuit types')
class Circuit(PrimaryModel):
"""
@ -131,6 +136,8 @@ class Circuit(PrimaryModel):
name='%(app_label)s_%(class)s_unique_provideraccount_cid'
),
)
verbose_name = _('circuit')
verbose_name_plural = _('circuits')
def __str__(self):
return self.cid
@ -217,6 +224,8 @@ class CircuitTermination(
name='%(app_label)s_%(class)s_unique_circuit_term_side'
),
)
verbose_name = _('circuit termination')
verbose_name_plural = _('circuit terminations')
def __str__(self):
return f'{self.circuit}: Termination {self.term_side}'

View File

@ -44,6 +44,8 @@ class Provider(PrimaryModel):
class Meta:
ordering = ['name']
verbose_name = _('provider')
verbose_name_plural = _('providers')
def __str__(self):
return self.name
@ -91,6 +93,8 @@ class ProviderAccount(PrimaryModel):
condition=~Q(name="")
),
)
verbose_name = _('provider account')
verbose_name_plural = _('provider accounts')
def __str__(self):
if self.name:
@ -129,6 +133,8 @@ class ProviderNetwork(PrimaryModel):
name='%(app_label)s_%(class)s_unique_provider_name'
),
)
verbose_name = _('provider network')
verbose_name_plural = _('provider networks')
def __str__(self):
return self.name

View File

@ -3,9 +3,15 @@ from django.conf import settings
from django.core.management.base import CommandError
from django.core.management.commands.makemigrations import Command as _Command
from django.db import models
from django.db.migrations.operations import AlterModelOptions
from utilities.migration import custom_deconstruct
# Monkey patch AlterModelOptions to ignore verbose name attributes
AlterModelOptions.ALTER_OPTION_KEYS.remove('verbose_name')
AlterModelOptions.ALTER_OPTION_KEYS.remove('verbose_name_plural')
# Set our custom deconstructor for fields
models.Field.deconstruct = custom_deconstruct

View File

@ -83,6 +83,8 @@ class DataSource(JobsMixin, PrimaryModel):
class Meta:
ordering = ('name',)
verbose_name = _('data source')
verbose_name_plural = _('data sources')
def __str__(self):
return f'{self.name}'
@ -300,6 +302,8 @@ class DataFile(models.Model):
indexes = [
models.Index(fields=('source', 'path'), name='core_datafile_source_path'),
]
verbose_name = _('data file')
verbose_name_plural = _('data files')
def __str__(self):
return self.path
@ -383,3 +387,5 @@ class AutoSyncRecord(models.Model):
indexes = (
models.Index(fields=('object_type', 'object_id')),
)
verbose_name = _('auto sync record')
verbose_name_plural = _('auto sync records')

View File

@ -56,6 +56,8 @@ class ManagedFile(SyncedDataMixin, models.Model):
indexes = [
models.Index(fields=('file_root', 'file_path'), name='core_managedfile_root_path'),
]
verbose_name = _('managed file')
verbose_name_plural = _('managed files')
def __str__(self):
return self.name

View File

@ -101,6 +101,8 @@ class Job(models.Model):
class Meta:
ordering = ['-created']
verbose_name = _('job')
verbose_name_plural = _('jobs')
def __str__(self):
return str(self.job_id)

View File

@ -91,6 +91,8 @@ class Cable(PrimaryModel):
class Meta:
ordering = ('pk',)
verbose_name = _('cable')
verbose_name_plural = _('cables')
def __init__(self, *args, a_terminations=None, b_terminations=None, **kwargs):
super().__init__(*args, **kwargs)
@ -292,6 +294,8 @@ class CableTermination(ChangeLoggedModel):
name='%(app_label)s_%(class)s_unique_termination'
),
)
verbose_name = _('cable termination')
verbose_name_plural = _('cable terminations')
def __str__(self):
return f'Cable {self.cable} to {self.termination}'
@ -427,6 +431,10 @@ class CablePath(models.Model):
)
_nodes = PathField()
class Meta:
verbose_name = _('cable path')
verbose_name_plural = _('cable paths')
def __str__(self):
return f"Path #{self.pk}: {len(self.path)} hops"

View File

@ -183,6 +183,10 @@ class ConsolePortTemplate(ModularComponentTemplateModel):
component_model = ConsolePort
class Meta(ModularComponentTemplateModel.Meta):
verbose_name = _('console port template')
verbose_name_plural = _('console port templates')
def instantiate(self, **kwargs):
return self.component_model(
name=self.resolve_name(kwargs.get('module')),
@ -213,6 +217,10 @@ class ConsoleServerPortTemplate(ModularComponentTemplateModel):
component_model = ConsoleServerPort
class Meta(ModularComponentTemplateModel.Meta):
verbose_name = _('console server port template')
verbose_name_plural = _('console server port templates')
def instantiate(self, **kwargs):
return self.component_model(
name=self.resolve_name(kwargs.get('module')),
@ -258,6 +266,10 @@ class PowerPortTemplate(ModularComponentTemplateModel):
component_model = PowerPort
class Meta(ModularComponentTemplateModel.Meta):
verbose_name = _('power port template')
verbose_name_plural = _('power port templates')
def instantiate(self, **kwargs):
return self.component_model(
name=self.resolve_name(kwargs.get('module')),
@ -316,6 +328,10 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
component_model = PowerOutlet
class Meta(ModularComponentTemplateModel.Meta):
verbose_name = _('power outlet template')
verbose_name_plural = _('power outlet templates')
def clean(self):
super().clean()
@ -410,6 +426,10 @@ class InterfaceTemplate(ModularComponentTemplateModel):
component_model = Interface
class Meta(ModularComponentTemplateModel.Meta):
verbose_name = _('interface template')
verbose_name_plural = _('interface templates')
def clean(self):
super().clean()
@ -503,6 +523,8 @@ class FrontPortTemplate(ModularComponentTemplateModel):
name='%(app_label)s_%(class)s_unique_rear_port_position'
),
)
verbose_name = _('front port template')
verbose_name_plural = _('front port templates')
def clean(self):
super().clean()
@ -579,6 +601,10 @@ class RearPortTemplate(ModularComponentTemplateModel):
component_model = RearPort
class Meta(ModularComponentTemplateModel.Meta):
verbose_name = _('rear port template')
verbose_name_plural = _('rear port templates')
def instantiate(self, **kwargs):
return self.component_model(
name=self.resolve_name(kwargs.get('module')),
@ -614,6 +640,10 @@ class ModuleBayTemplate(ComponentTemplateModel):
component_model = ModuleBay
class Meta(ComponentTemplateModel.Meta):
verbose_name = _('module bay template')
verbose_name_plural = _('module bay templates')
def instantiate(self, device):
return self.component_model(
device=device,
@ -638,6 +668,10 @@ class DeviceBayTemplate(ComponentTemplateModel):
"""
component_model = DeviceBay
class Meta(ComponentTemplateModel.Meta):
verbose_name = _('device bay template')
verbose_name_plural = _('device bay templates')
def instantiate(self, device):
return self.component_model(
device=device,
@ -720,6 +754,8 @@ class InventoryItemTemplate(MPTTModel, ComponentTemplateModel):
name='%(app_label)s_%(class)s_unique_device_type_parent_name'
),
)
verbose_name = _('inventory item template')
verbose_name_plural = _('inventory item templates')
def instantiate(self, **kwargs):
parent = InventoryItem.objects.get(name=self.parent.name, **kwargs) if self.parent else None

View File

@ -298,6 +298,10 @@ class ConsolePort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
clone_fields = ('device', 'module', 'type', 'speed')
class Meta(ModularComponentModel.Meta):
verbose_name = _('console port')
verbose_name_plural = _('console ports')
def get_absolute_url(self):
return reverse('dcim:consoleport', kwargs={'pk': self.pk})
@ -323,6 +327,10 @@ class ConsoleServerPort(ModularComponentModel, CabledObjectModel, PathEndpoint,
clone_fields = ('device', 'module', 'type', 'speed')
class Meta(ModularComponentModel.Meta):
verbose_name = _('console server port')
verbose_name_plural = _('console server ports')
def get_absolute_url(self):
return reverse('dcim:consoleserverport', kwargs={'pk': self.pk})
@ -359,6 +367,10 @@ class PowerPort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracking
clone_fields = ('device', 'module', 'maximum_draw', 'allocated_draw')
class Meta(ModularComponentModel.Meta):
verbose_name = _('power port')
verbose_name_plural = _('power ports')
def get_absolute_url(self):
return reverse('dcim:powerport', kwargs={'pk': self.pk})
@ -473,6 +485,10 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
clone_fields = ('device', 'module', 'type', 'power_port', 'feed_leg')
class Meta(ModularComponentModel.Meta):
verbose_name = _('power outlet')
verbose_name_plural = _('power outlets')
def get_absolute_url(self):
return reverse('dcim:poweroutlet', kwargs={'pk': self.pk})
@ -718,6 +734,8 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
class Meta(ModularComponentModel.Meta):
ordering = ('device', CollateAsChar('_name'))
verbose_name = _('interface')
verbose_name_plural = _('interfaces')
def get_absolute_url(self):
return reverse('dcim:interface', kwargs={'pk': self.pk})
@ -977,6 +995,8 @@ class FrontPort(ModularComponentModel, CabledObjectModel, TrackingModelMixin):
name='%(app_label)s_%(class)s_unique_rear_port_position'
),
)
verbose_name = _('front port')
verbose_name_plural = _('front ports')
def get_absolute_url(self):
return reverse('dcim:frontport', kwargs={'pk': self.pk})
@ -1032,6 +1052,10 @@ class RearPort(ModularComponentModel, CabledObjectModel, TrackingModelMixin):
)
clone_fields = ('device', 'type', 'color', 'positions')
class Meta(ModularComponentModel.Meta):
verbose_name = _('rear port')
verbose_name_plural = _('rear ports')
def get_absolute_url(self):
return reverse('dcim:rearport', kwargs={'pk': self.pk})
@ -1066,6 +1090,10 @@ class ModuleBay(ComponentModel, TrackingModelMixin):
clone_fields = ('device',)
class Meta(ComponentModel.Meta):
verbose_name = _('module bay')
verbose_name_plural = _('module bays')
def get_absolute_url(self):
return reverse('dcim:modulebay', kwargs={'pk': self.pk})
@ -1084,6 +1112,10 @@ class DeviceBay(ComponentModel, TrackingModelMixin):
clone_fields = ('device',)
class Meta(ComponentModel.Meta):
verbose_name = _('device bay')
verbose_name_plural = _('device bays')
def get_absolute_url(self):
return reverse('dcim:devicebay', kwargs={'pk': self.pk})
@ -1125,6 +1157,11 @@ class InventoryItemRole(OrganizationalModel):
default=ColorChoices.COLOR_GREY
)
class Meta:
ordering = ('name',)
verbose_name = _('inventory item role')
verbose_name_plural = _('inventory item roles')
def get_absolute_url(self):
return reverse('dcim:inventoryitemrole', args=[self.pk])
@ -1209,6 +1246,8 @@ class InventoryItem(MPTTModel, ComponentModel, TrackingModelMixin):
name='%(app_label)s_%(class)s_unique_device_parent_name'
),
)
verbose_name = _('inventory item')
verbose_name_plural = _('inventory items')
def get_absolute_url(self):
return reverse('dcim:inventoryitem', kwargs={'pk': self.pk})

View File

@ -53,6 +53,11 @@ class Manufacturer(OrganizationalModel):
to='tenancy.ContactAssignment'
)
class Meta:
ordering = ('name',)
verbose_name = _('manufacturer')
verbose_name_plural = _('manufacturers')
def get_absolute_url(self):
return reverse('dcim:manufacturer', args=[self.pk])
@ -199,6 +204,8 @@ class DeviceType(PrimaryModel, WeightMixin):
name='%(app_label)s_%(class)s_unique_manufacturer_slug'
),
)
verbose_name = _('device type')
verbose_name_plural = _('device types')
def __str__(self):
return self.model
@ -400,6 +407,8 @@ class ModuleType(PrimaryModel, WeightMixin):
name='%(app_label)s_%(class)s_unique_manufacturer_model'
),
)
verbose_name = _('module type')
verbose_name_plural = _('module types')
def __str__(self):
return self.model
@ -477,6 +486,11 @@ class DeviceRole(OrganizationalModel):
null=True
)
class Meta:
ordering = ('name',)
verbose_name = _('device role')
verbose_name_plural = _('device roles')
def get_absolute_url(self):
return reverse('dcim:devicerole', args=[self.pk])
@ -502,6 +516,11 @@ class Platform(OrganizationalModel):
null=True
)
class Meta:
ordering = ('name',)
verbose_name = _('platform')
verbose_name_plural = _('platforms')
def get_absolute_url(self):
return reverse('dcim:platform', args=[self.pk])
@ -789,6 +808,8 @@ class Device(PrimaryModel, ConfigContextModel, TrackingModelMixin):
name='%(app_label)s_%(class)s_unique_virtual_chassis_vc_position'
),
)
verbose_name = _('device')
verbose_name_plural = _('devices')
def __str__(self):
if self.name and self.asset_tag:
@ -1182,6 +1203,8 @@ class Module(PrimaryModel, ConfigContextModel):
class Meta:
ordering = ('module_bay',)
verbose_name = _('module')
verbose_name_plural = _('modules')
def __str__(self):
return f'{self.module_bay.name}: {self.module_type} ({self.pk})'
@ -1314,7 +1337,8 @@ class VirtualChassis(PrimaryModel):
class Meta:
ordering = ['name']
verbose_name_plural = 'virtual chassis'
verbose_name = _('virtual chassis')
verbose_name_plural = _('virtual chassis')
def __str__(self):
return self.name
@ -1415,6 +1439,8 @@ class VirtualDeviceContext(PrimaryModel):
name='%(app_label)s_%(class)s_device_name'
),
)
verbose_name = _('virtual device context')
verbose_name_plural = _('virtual device contexts')
def __str__(self):
return self.name

View File

@ -60,6 +60,8 @@ class PowerPanel(PrimaryModel):
name='%(app_label)s_%(class)s_unique_site_name'
),
)
verbose_name = _('power panel')
verbose_name_plural = _('power panels')
def __str__(self):
return self.name
@ -166,6 +168,8 @@ class PowerFeed(PrimaryModel, PathEndpoint, CabledObjectModel):
name='%(app_label)s_%(class)s_unique_power_panel_name'
),
)
verbose_name = _('power feed')
verbose_name_plural = _('power feeds')
def __str__(self):
return self.name

View File

@ -43,6 +43,11 @@ class RackRole(OrganizationalModel):
default=ColorChoices.COLOR_GREY
)
class Meta:
ordering = ('name',)
verbose_name = _('rack role')
verbose_name_plural = _('rack roles')
def get_absolute_url(self):
return reverse('dcim:rackrole', args=[self.pk])
@ -216,6 +221,8 @@ class Rack(PrimaryModel, WeightMixin):
name='%(app_label)s_%(class)s_unique_location_facility_id'
),
)
verbose_name = _('rack')
verbose_name_plural = _('racks')
def __str__(self):
if self.facility_id:
@ -538,6 +545,8 @@ class RackReservation(PrimaryModel):
class Meta:
ordering = ['created', 'pk']
verbose_name = _('rack reservation')
verbose_name_plural = _('rack reservations')
def __str__(self):
return "Reservation for rack {}".format(self.rack)

View File

@ -62,6 +62,8 @@ class Region(NestedGroupModel):
violation_error_message=_("A top-level region with this slug already exists.")
),
)
verbose_name = _('region')
verbose_name_plural = _('regions')
def get_absolute_url(self):
return reverse('dcim:region', args=[self.pk])
@ -117,6 +119,8 @@ class SiteGroup(NestedGroupModel):
violation_error_message=_("A top-level site group with this slug already exists.")
),
)
verbose_name = _('site group')
verbose_name_plural = _('site groups')
def get_absolute_url(self):
return reverse('dcim:sitegroup', args=[self.pk])
@ -244,6 +248,8 @@ class Site(PrimaryModel):
class Meta:
ordering = ('_name',)
verbose_name = _('site')
verbose_name_plural = _('sites')
def __str__(self):
return self.name
@ -326,6 +332,8 @@ class Location(NestedGroupModel):
violation_error_message=_("A location with this slug already exists within the specified site.")
),
)
verbose_name = _('location')
verbose_name_plural = _('locations')
def get_absolute_url(self):
return reverse('dcim:location', args=[self.pk])

View File

@ -93,6 +93,8 @@ class ObjectChange(models.Model):
class Meta:
ordering = ['-time']
verbose_name = _('object change')
verbose_name_plural = _('object changes')
def __str__(self):
return '{} {} {} by {}'.format(

View File

@ -125,6 +125,8 @@ class ConfigContext(SyncedDataMixin, CloningMixin, ChangeLoggedModel):
class Meta:
ordering = ['weight', 'name']
verbose_name = _('config context')
verbose_name_plural = _('config contexts')
def __str__(self):
return self.name
@ -233,6 +235,8 @@ class ConfigTemplate(SyncedDataMixin, ExportTemplatesMixin, TagsMixin, ChangeLog
class Meta:
ordering = ('name',)
verbose_name = _('config template')
verbose_name_plural = _('config templates')
def __str__(self):
return self.name

View File

@ -202,6 +202,8 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
class Meta:
ordering = ['group_name', 'weight', 'name']
verbose_name = _('custom field')
verbose_name_plural = _('custom fields')
def __str__(self):
return self.label or self.name.replace('_', ' ').capitalize()
@ -710,6 +712,8 @@ class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel
class Meta:
ordering = ('name',)
verbose_name = _('custom field choice set')
verbose_name_plural = _('custom field choice sets')
def __str__(self):
return self.name

View File

@ -25,7 +25,8 @@ class Dashboard(models.Model):
)
class Meta:
pass
verbose_name = _('dashboard')
verbose_name_plural = _('dashboards')
def get_widget(self, id):
"""

View File

@ -165,6 +165,8 @@ class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedMo
name='%(app_label)s_%(class)s_unique_payload_url_types'
),
)
verbose_name = _('webhook')
verbose_name_plural = _('webhooks')
def __str__(self):
return self.name
@ -284,6 +286,8 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
class Meta:
ordering = ['group_name', 'weight', 'name']
verbose_name = _('custom link')
verbose_name_plural = _('custom links')
def __str__(self):
return self.name
@ -371,6 +375,8 @@ class ExportTemplate(SyncedDataMixin, CloningMixin, ExportTemplatesMixin, Change
class Meta:
ordering = ('name',)
verbose_name = _('export template')
verbose_name_plural = _('export templates')
def __str__(self):
return self.name
@ -482,6 +488,8 @@ class SavedFilter(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
class Meta:
ordering = ('weight', 'name')
verbose_name = _('saved filter')
verbose_name_plural = _('saved filters')
def __str__(self):
return self.name
@ -544,6 +552,8 @@ class ImageAttachment(ChangeLoggedModel):
class Meta:
ordering = ('name', 'pk') # name may be non-unique
verbose_name = _('image attachment')
verbose_name_plural = _('image attachments')
def __str__(self):
if self.name:
@ -622,7 +632,8 @@ class JournalEntry(CustomFieldsMixin, CustomLinksMixin, TagsMixin, ExportTemplat
class Meta:
ordering = ('-created',)
verbose_name_plural = 'journal entries'
verbose_name = _('journal entry')
verbose_name_plural = _('journal entries')
def __str__(self):
created = timezone.localtime(self.created)
@ -677,6 +688,8 @@ class Bookmark(models.Model):
name='%(app_label)s_%(class)s_unique_per_object_and_user'
),
)
verbose_name = _('bookmark')
verbose_name_plural = _('bookmarks')
def __str__(self):
if self.object:
@ -707,6 +720,8 @@ class ConfigRevision(models.Model):
class Meta:
ordering = ['-created']
verbose_name = _('config revision')
verbose_name_plural = _('config revisions')
def __str__(self):
return f'Config revision #{self.pk} ({self.created})'

View File

@ -4,6 +4,7 @@ from functools import cached_property
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from core.choices import ManagedFileRootPathChoices
from core.models import ManagedFile
@ -42,6 +43,8 @@ class ReportModule(PythonModuleMixin, JobsMixin, ManagedFile):
class Meta:
proxy = True
verbose_name = _('report module')
verbose_name_plural = _('report modules')
def get_absolute_url(self):
return reverse('extras:report_list')

View File

@ -4,6 +4,7 @@ from functools import cached_property
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from core.choices import ManagedFileRootPathChoices
from core.models import ManagedFile
@ -42,6 +43,8 @@ class ScriptModule(PythonModuleMixin, JobsMixin, ManagedFile):
class Meta:
proxy = True
verbose_name = _('script module')
verbose_name_plural = _('script modules')
def get_absolute_url(self):
return reverse('extras:script_list')

View File

@ -51,6 +51,8 @@ class CachedValue(models.Model):
class Meta:
ordering = ('weight', 'object_type', 'object_id')
verbose_name = _('cached value')
verbose_name_plural = _('cached values')
def __str__(self):
return f'{self.object_type} {self.object_id}: {self.field}={self.value}'

View File

@ -41,6 +41,8 @@ class Branch(ChangeLoggedModel):
class Meta:
ordering = ('name',)
verbose_name = _('branch')
verbose_name_plural = _('branches')
def __str__(self):
return f'{self.name} ({self.pk})'
@ -89,6 +91,8 @@ class StagedChange(ChangeLoggedModel):
class Meta:
ordering = ('pk',)
verbose_name = _('staged change')
verbose_name_plural = _('staged changes')
def __str__(self):
action = self.get_action_display()

View File

@ -50,6 +50,8 @@ class Tag(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel, TagBase):
class Meta:
ordering = ['name']
verbose_name = _('tag')
verbose_name_plural = _('tags')
def get_absolute_url(self):
return reverse('extras:tag', args=[self.pk])
@ -75,3 +77,5 @@ class TaggedItem(GenericTaggedItemBase):
class Meta:
indexes = [models.Index(fields=["content_type", "object_id"])]
verbose_name = _('tagged item')
verbose_name_plural = _('tagged items')

View File

@ -48,8 +48,8 @@ class ASNRange(OrganizationalModel):
class Meta:
ordering = ('name',)
verbose_name = 'ASN range'
verbose_name_plural = 'ASN ranges'
verbose_name = _('ASN range')
verbose_name_plural = _('ASN ranges')
def __str__(self):
return f'{self.name} ({self.range_as_string()})'
@ -122,8 +122,8 @@ class ASN(PrimaryModel):
class Meta:
ordering = ['asn']
verbose_name = 'ASN'
verbose_name_plural = 'ASNs'
verbose_name = _('ASN')
verbose_name_plural = _('ASNs')
def __str__(self):
return f'AS{self.asn_with_asdot}'

View File

@ -54,7 +54,8 @@ class FHRPGroup(PrimaryModel):
class Meta:
ordering = ['protocol', 'group_id', 'pk']
verbose_name = 'FHRP group'
verbose_name = _('FHRP group')
verbose_name_plural = _('FHRP groups')
def __str__(self):
name = ''
@ -108,6 +109,7 @@ class FHRPGroupAssignment(ChangeLoggedModel):
),
)
verbose_name = _('FHRP group assignment')
verbose_name_plural = _('FHRP group assignments')
def __str__(self):
return f'{self.interface}: {self.group} ({self.priority})'

View File

@ -111,6 +111,8 @@ class Aggregate(GetAvailablePrefixesMixin, PrimaryModel):
class Meta:
ordering = ('prefix', 'pk') # prefix may be non-unique
verbose_name = _('aggregate')
verbose_name_plural = _('aggregates')
def __str__(self):
return str(self.prefix)
@ -188,6 +190,8 @@ class Role(OrganizationalModel):
class Meta:
ordering = ('weight', 'name')
verbose_name = _('role')
verbose_name_plural = _('roles')
def __str__(self):
return self.name
@ -279,7 +283,8 @@ class Prefix(GetAvailablePrefixesMixin, PrimaryModel):
class Meta:
ordering = (F('vrf').asc(nulls_first=True), 'prefix', 'pk') # (vrf, prefix) may be non-unique
verbose_name_plural = 'prefixes'
verbose_name = _('prefix')
verbose_name_plural = _('prefixes')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@ -532,8 +537,8 @@ class IPRange(PrimaryModel):
class Meta:
ordering = (F('vrf').asc(nulls_first=True), 'start_address', 'pk') # (vrf, start_address) may be non-unique
verbose_name = 'IP range'
verbose_name_plural = 'IP ranges'
verbose_name = _('IP range')
verbose_name_plural = _('IP ranges')
def __str__(self):
return self.name
@ -783,8 +788,8 @@ class IPAddress(PrimaryModel):
indexes = [
models.Index(Cast(Host('address'), output_field=IPAddressField()), name='ipam_ipaddress_host'),
]
verbose_name = 'IP address'
verbose_name_plural = 'IP addresses'
verbose_name = _('IP address')
verbose_name_plural = _('IP addresses')
def __str__(self):
return str(self.address)

View File

@ -62,7 +62,8 @@ class L2VPN(PrimaryModel):
class Meta:
ordering = ('name', 'identifier')
verbose_name = 'L2VPN'
verbose_name = _('L2VPN')
verbose_name_plural = _('L2VPNs')
def __str__(self):
if self.identifier:
@ -105,13 +106,14 @@ class L2VPNTermination(NetBoxModel):
class Meta:
ordering = ('l2vpn',)
verbose_name = 'L2VPN termination'
constraints = (
models.UniqueConstraint(
fields=('assigned_object_type', 'assigned_object_id'),
name='ipam_l2vpntermination_assigned_object'
),
)
verbose_name = _('L2VPN termination')
verbose_name_plural = _('L2VPN terminations')
def __str__(self):
if self.pk is not None:

View File

@ -56,6 +56,8 @@ class ServiceTemplate(ServiceBase, PrimaryModel):
class Meta:
ordering = ('name',)
verbose_name = _('service template')
verbose_name_plural = _('service templates')
def get_absolute_url(self):
return reverse('ipam:servicetemplate', args=[self.pk])
@ -97,6 +99,8 @@ class Service(ServiceBase, PrimaryModel):
class Meta:
ordering = ('protocol', 'ports', 'pk') # (protocol, port) may be non-unique
verbose_name = _('service')
verbose_name_plural = _('services')
def get_absolute_url(self):
return reverse('ipam:service', args=[self.pk])

View File

@ -79,8 +79,8 @@ class VLANGroup(OrganizationalModel):
name='%(app_label)s_%(class)s_unique_scope_slug'
),
)
verbose_name = 'VLAN group'
verbose_name_plural = 'VLAN groups'
verbose_name = _('VLAN group')
verbose_name_plural = _('VLAN groups')
def get_absolute_url(self):
return reverse('ipam:vlangroup', args=[self.pk])
@ -204,8 +204,8 @@ class VLAN(PrimaryModel):
name='%(app_label)s_%(class)s_unique_group_name'
),
)
verbose_name = 'VLAN'
verbose_name_plural = 'VLANs'
verbose_name = _('VLAN')
verbose_name_plural = _('VLANs')
def __str__(self):
return f'{self.name} ({self.vid})'

View File

@ -59,8 +59,8 @@ class VRF(PrimaryModel):
class Meta:
ordering = ('name', 'rd', 'pk') # (name, rd) may be non-unique
verbose_name = 'VRF'
verbose_name_plural = 'VRFs'
verbose_name = _('VRF')
verbose_name_plural = _('VRFs')
def __str__(self):
if self.rd:
@ -91,6 +91,8 @@ class RouteTarget(PrimaryModel):
class Meta:
ordering = ['name']
verbose_name = _('route target')
verbose_name_plural = _('route targets')
def __str__(self):
return self.name

View File

@ -28,6 +28,8 @@ class ContactGroup(NestedGroupModel):
name='%(app_label)s_%(class)s_unique_parent_name'
),
)
verbose_name = _('contact group')
verbose_name_plural = _('contact groups')
def get_absolute_url(self):
return reverse('tenancy:contactgroup', args=[self.pk])
@ -40,6 +42,11 @@ class ContactRole(OrganizationalModel):
def get_absolute_url(self):
return reverse('tenancy:contactrole', args=[self.pk])
class Meta:
ordering = ('name',)
verbose_name = _('contact role')
verbose_name_plural = _('contact roles')
class Contact(PrimaryModel):
"""
@ -92,6 +99,8 @@ class Contact(PrimaryModel):
name='%(app_label)s_%(class)s_unique_group_name'
),
)
verbose_name = _('contact')
verbose_name_plural = _('contacts')
def __str__(self):
return self.name
@ -137,6 +146,8 @@ class ContactAssignment(ChangeLoggedModel, TagsMixin):
name='%(app_label)s_%(class)s_unique_object_contact_role'
),
)
verbose_name = _('contact assignment')
verbose_name_plural = _('contact assignments')
def __str__(self):
if self.priority:

View File

@ -29,6 +29,8 @@ class TenantGroup(NestedGroupModel):
class Meta:
ordering = ['name']
verbose_name = _('tenant group')
verbose_name_plural = _('tenant groups')
def get_absolute_url(self):
return reverse('tenancy:tenantgroup', args=[self.pk])
@ -88,6 +90,8 @@ class Tenant(PrimaryModel):
condition=Q(group__isnull=True)
),
)
verbose_name = _('tenant')
verbose_name_plural = _('tenants')
def __str__(self):
return self.name

View File

@ -49,9 +49,10 @@ class NetBoxUser(User):
objects = NetBoxUserManager()
class Meta:
verbose_name = 'User'
proxy = True
ordering = ('username',)
verbose_name = _('user')
verbose_name_plural = _('users')
def get_absolute_url(self):
return reverse('users:netboxuser', args=[self.pk])
@ -72,9 +73,10 @@ class NetBoxGroup(Group):
objects = NetBoxGroupManager()
class Meta:
verbose_name = 'Group'
proxy = True
ordering = ('name',)
verbose_name = _('group')
verbose_name_plural = _('groups')
def get_absolute_url(self):
return reverse('users:netboxgroup', args=[self.pk])
@ -99,7 +101,8 @@ class UserConfig(models.Model):
class Meta:
ordering = ['user']
verbose_name = verbose_name_plural = _('User Preferences')
verbose_name = _('user preferences')
verbose_name_plural = _('user preferences')
def get(self, path, default=None):
"""
@ -281,6 +284,10 @@ class Token(models.Model):
objects = RestrictedQuerySet.as_manager()
class Meta:
verbose_name = _('token')
verbose_name_plural = _('tokens')
def __str__(self):
return self.key if settings.ALLOW_TOKEN_RETRIEVAL else self.partial
@ -373,7 +380,8 @@ class ObjectPermission(models.Model):
class Meta:
ordering = ['name']
verbose_name = _("permission")
verbose_name = _('permission')
verbose_name_plural = _('permissions')
def __str__(self):
return self.name

View File

@ -19,6 +19,11 @@ class ClusterType(OrganizationalModel):
"""
A type of Cluster.
"""
class Meta:
ordering = ('name',)
verbose_name = _('cluster type')
verbose_name_plural = _('cluster types')
def get_absolute_url(self):
return reverse('virtualization:clustertype', args=[self.pk])
@ -38,6 +43,11 @@ class ClusterGroup(OrganizationalModel):
to='tenancy.ContactAssignment'
)
class Meta:
ordering = ('name',)
verbose_name = _('cluster group')
verbose_name_plural = _('cluster groups')
def get_absolute_url(self):
return reverse('virtualization:clustergroup', args=[self.pk])
@ -114,6 +124,8 @@ class Cluster(PrimaryModel):
name='%(app_label)s_%(class)s_unique_site_name'
),
)
verbose_name = _('cluster')
verbose_name_plural = _('clusters')
def __str__(self):
return self.name

View File

@ -157,6 +157,8 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
violation_error_message=_("Virtual machine name must be unique per cluster.")
),
)
verbose_name = _('virtual machine')
verbose_name_plural = _('virtual machines')
def __str__(self):
return self.name
@ -307,7 +309,8 @@ class VMInterface(NetBoxModel, BaseInterface, TrackingModelMixin):
name='%(app_label)s_%(class)s_unique_virtual_machine_name'
),
)
verbose_name = 'interface'
verbose_name = _('interface')
verbose_name_plural = _('interfaces')
def __str__(self):
return self.name

View File

@ -66,7 +66,8 @@ class WirelessLANGroup(NestedGroupModel):
name='%(app_label)s_%(class)s_unique_parent_name'
),
)
verbose_name = 'Wireless LAN Group'
verbose_name = _('wireless LAN group')
verbose_name_plural = _('wireless LAN groups')
def get_absolute_url(self):
return reverse('wireless:wirelesslangroup', args=[self.pk])
@ -112,7 +113,8 @@ class WirelessLAN(WirelessAuthenticationBase, PrimaryModel):
class Meta:
ordering = ('ssid', 'pk')
verbose_name = 'Wireless LAN'
verbose_name = _('wireless LAN')
verbose_name_plural = _('wireless LANs')
def __str__(self):
return self.ssid
@ -194,6 +196,8 @@ class WirelessLink(WirelessAuthenticationBase, PrimaryModel):
name='%(app_label)s_%(class)s_unique_interfaces'
),
)
verbose_name = _('wireless link')
verbose_name_plural = _('wireless links')
def __str__(self):
return self.ssid or f'#{self.pk}'