netbox-plugin-dns 1.1.4__py3-none-any.whl → 1.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of netbox-plugin-dns might be problematic. Click here for more details.

Files changed (35) hide show
  1. netbox_dns/__init__.py +18 -4
  2. netbox_dns/api/views.py +1 -1
  3. netbox_dns/filtersets/record.py +0 -1
  4. netbox_dns/filtersets/zone.py +1 -2
  5. netbox_dns/forms/record.py +11 -7
  6. netbox_dns/forms/view.py +2 -3
  7. netbox_dns/forms/zone.py +8 -9
  8. netbox_dns/forms/zone_template.py +5 -5
  9. netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
  10. netbox_dns/models/nameserver.py +4 -8
  11. netbox_dns/models/record.py +18 -34
  12. netbox_dns/models/record_template.py +4 -4
  13. netbox_dns/models/view.py +2 -3
  14. netbox_dns/models/zone.py +78 -32
  15. netbox_dns/tables/record.py +14 -2
  16. netbox_dns/tables/zone.py +1 -2
  17. netbox_dns/template_content.py +16 -0
  18. netbox_dns/templates/netbox_dns/record.html +12 -0
  19. netbox_dns/templates/netbox_dns/view.html +1 -1
  20. netbox_dns/templates/netbox_dns/zone/delegation_record.html +18 -0
  21. netbox_dns/templates/netbox_dns/zone.html +1 -1
  22. netbox_dns/utilities/__init__.py +1 -0
  23. netbox_dns/utilities/dns.py +12 -0
  24. netbox_dns/utilities/ipam_dnssync.py +10 -13
  25. netbox_dns/views/nameserver.py +3 -3
  26. netbox_dns/views/record.py +44 -11
  27. netbox_dns/views/registrar.py +1 -1
  28. netbox_dns/views/registration_contact.py +1 -1
  29. netbox_dns/views/view.py +2 -2
  30. netbox_dns/views/zone.py +49 -20
  31. {netbox_plugin_dns-1.1.4.dist-info → netbox_plugin_dns-1.1.5.dist-info}/METADATA +2 -1
  32. {netbox_plugin_dns-1.1.4.dist-info → netbox_plugin_dns-1.1.5.dist-info}/RECORD +35 -33
  33. {netbox_plugin_dns-1.1.4.dist-info → netbox_plugin_dns-1.1.5.dist-info}/WHEEL +1 -1
  34. {netbox_plugin_dns-1.1.4.dist-info → netbox_plugin_dns-1.1.5.dist-info}/LICENSE +0 -0
  35. {netbox_plugin_dns-1.1.4.dist-info → netbox_plugin_dns-1.1.5.dist-info}/top_level.txt +0 -0
netbox_dns/__init__.py CHANGED
@@ -1,12 +1,18 @@
1
- from django.conf import settings
2
1
  from django.utils.translation import gettext_lazy as _
2
+ from django.core.exceptions import ImproperlyConfigured
3
3
 
4
4
  from netbox.plugins import PluginConfig
5
+ from netbox.plugins.utils import get_plugin_config
5
6
  from ipam.choices import IPAddressStatusChoices
6
7
 
7
8
  from netbox_dns.choices import RecordTypeChoices, RecordStatusChoices, ZoneStatusChoices
8
9
 
9
- __version__ = "1.1.4"
10
+ __version__ = "1.1.5"
11
+
12
+
13
+ def _check_list(setting):
14
+ if not isinstance(get_plugin_config("netbox_dns", setting), list):
15
+ raise ImproperlyConfigured(f"{setting} must be a list")
10
16
 
11
17
 
12
18
  class DNSConfig(PluginConfig):
@@ -53,7 +59,7 @@ class DNSConfig(PluginConfig):
53
59
  "enable_root_zones": False,
54
60
  "enforce_unique_records": True,
55
61
  "enforce_unique_rrset_ttl": True,
56
- "menu_name": "NetBox DNS",
62
+ "menu_name": "DNS",
57
63
  "top_level_menu": True,
58
64
  }
59
65
  base_url = "netbox-dns"
@@ -61,10 +67,18 @@ class DNSConfig(PluginConfig):
61
67
  def ready(self):
62
68
  super().ready()
63
69
 
64
- if not settings.PLUGINS_CONFIG["netbox_dns"].get("dnssync_disabled"):
70
+ if not get_plugin_config("netbox_dns", "dnssync_disabled"):
65
71
  import netbox_dns.signals.ipam_dnssync # noqa: F401
66
72
  import netbox_dns.tables.ipam_dnssync # noqa: F401
67
73
 
74
+ for setting in (
75
+ "zone_active_status",
76
+ "record_active_status",
77
+ "dnssync_ipaddress_active_status",
78
+ "tolerate_leading_underscore_types",
79
+ ):
80
+ _check_list(setting)
81
+
68
82
 
69
83
  #
70
84
  # Initialize plugin config
netbox_dns/api/views.py CHANGED
@@ -71,7 +71,7 @@ class NameServerViewSet(NetBoxModelViewSet):
71
71
 
72
72
 
73
73
  class RecordViewSet(NetBoxModelViewSet):
74
- queryset = Record.objects.all().prefetch_related("zone", "zone__view", "tenant")
74
+ queryset = Record.objects.prefetch_related("zone", "zone__view", "tenant")
75
75
  serializer_class = RecordSerializer
76
76
  filterset_class = RecordFilterSet
77
77
 
@@ -92,7 +92,6 @@ class RecordFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
92
92
  "ttl",
93
93
  "value",
94
94
  "disable_ptr",
95
- "active",
96
95
  "managed",
97
96
  )
98
97
 
@@ -3,7 +3,6 @@ import netaddr
3
3
  import django_filters
4
4
  from django.db.models import Q
5
5
  from django.utils.translation import gettext as _
6
- from django.utils.translation import pgettext as _p
7
6
 
8
7
  from netbox.filtersets import NetBoxModelFilterSet
9
8
  from tenancy.filtersets import TenancyFilterSet
@@ -28,7 +27,7 @@ class ZoneFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
28
27
  queryset=View.objects.all(),
29
28
  field_name="view__name",
30
29
  to_field_name="name",
31
- label=_p("DNS", "View"),
30
+ label=_("View"),
32
31
  )
33
32
  # DEPRECATED: Remove in 1.1
34
33
  name_server_id = django_filters.ModelMultipleChoiceFilter(
@@ -1,6 +1,5 @@
1
1
  from django import forms
2
2
  from django.utils.translation import gettext_lazy as _
3
- from django.utils.translation import pgettext_lazy as _p
4
3
 
5
4
  from netbox.forms import (
6
5
  NetBoxModelBulkEditForm,
@@ -48,7 +47,7 @@ class RecordForm(TenancyForm, NetBoxModelForm):
48
47
  initial_params={
49
48
  "zone": "$zone",
50
49
  },
51
- label=_p("DNS", "View"),
50
+ label=_("View"),
52
51
  )
53
52
  zone = DynamicModelChoiceField(
54
53
  queryset=Zone.objects.all(),
@@ -187,23 +186,28 @@ class RecordImportForm(NetBoxModelImportForm):
187
186
  pass
188
187
 
189
188
  if view is not None:
190
- self.fields["zone"].queryset = Zone.objects.filter(view=view)
189
+ self.fields["zone"].queryset = view.zone_set
191
190
  else:
192
- self.fields["zone"].queryset = Zone.objects.filter(
193
- view=View.get_default_view()
194
- )
191
+ self.fields["zone"].queryset = View.get_default_view().zone_set
195
192
 
196
193
  zone = CSVModelChoiceField(
197
194
  queryset=Zone.objects.all(),
198
195
  to_field_name="name",
199
196
  required=True,
200
197
  label=_("Zone"),
198
+ error_messages={
199
+ "invalid_choice": _("Zone %(value)s not found"),
200
+ },
201
201
  )
202
202
  view = CSVModelChoiceField(
203
203
  queryset=View.objects.all(),
204
204
  to_field_name="name",
205
205
  required=False,
206
- label=_p("DNS", "View"),
206
+ label=_("View"),
207
+ error_messages={
208
+ "invalid_choice": _("View %(value)s not found"),
209
+ },
210
+ help_text=_("This field is required if the zone is not in the default view"),
207
211
  )
208
212
  type = CSVChoiceField(
209
213
  choices=RecordTypeChoices,
netbox_dns/forms/view.py CHANGED
@@ -3,7 +3,6 @@ from django.conf import settings
3
3
  from django.core.exceptions import ValidationError, FieldError
4
4
  from django.db.models import Q, Count
5
5
  from django.utils.translation import gettext_lazy as _
6
- from django.utils.translation import pgettext_lazy as _p
7
6
 
8
7
  from netbox.forms import (
9
8
  NetBoxModelBulkEditForm,
@@ -127,7 +126,7 @@ class ViewForm(ViewPrefixUpdateMixin, TenancyForm, NetBoxModelForm):
127
126
  )
128
127
 
129
128
  fieldsets = (
130
- FieldSet("name", "default_view", "description", name=_p("DNS", "View")),
129
+ FieldSet("name", "default_view", "description", name=_("View")),
131
130
  FieldSet("prefixes", "ip_address_filter"),
132
131
  FieldSet("tenant_group", "tenant", name=_("Tenancy")),
133
132
  FieldSet("tags", name=_("Tags")),
@@ -302,7 +301,7 @@ class ViewPrefixEditForm(forms.ModelForm):
302
301
 
303
302
  if not views.exists():
304
303
  if (parent := prefix.get_parents().last()) is not None:
305
- check_views = parent.netbox_dns_views.all().difference(old_views)
304
+ check_views = parent.netbox_dns_views.difference(old_views)
306
305
 
307
306
  else:
308
307
  check_views = views.difference(old_views)
netbox_dns/forms/zone.py CHANGED
@@ -4,7 +4,6 @@ from django.conf import settings
4
4
  from django.core.validators import MinValueValidator, MaxValueValidator
5
5
  from django.core.exceptions import ValidationError
6
6
  from django.utils.translation import gettext_lazy as _
7
- from django.utils.translation import pgettext_lazy as _p
8
7
 
9
8
  from netbox.forms import (
10
9
  NetBoxModelBulkEditForm,
@@ -385,7 +384,7 @@ class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
385
384
  view_id = DynamicModelMultipleChoiceField(
386
385
  queryset=View.objects.all(),
387
386
  required=False,
388
- label=_p("DNS", "View"),
387
+ label=_("View"),
389
388
  )
390
389
  status = forms.MultipleChoiceField(
391
390
  choices=ZoneStatusChoices,
@@ -476,7 +475,7 @@ class ZoneImportForm(ZoneTemplateUpdateMixin, NetBoxModelImportForm):
476
475
  required=False,
477
476
  to_field_name="name",
478
477
  error_messages={
479
- "invalid_choice": _("View not found."),
478
+ "invalid_choice": _("View %(value)s not found"),
480
479
  },
481
480
  label=_("View"),
482
481
  )
@@ -505,7 +504,7 @@ class ZoneImportForm(ZoneTemplateUpdateMixin, NetBoxModelImportForm):
505
504
  required=False,
506
505
  to_field_name="name",
507
506
  error_messages={
508
- "invalid_choice": _("Nameserver not found."),
507
+ "invalid_choice": _("Nameserver %(value)s not found"),
509
508
  },
510
509
  help_text=_("Primary nameserver for the zone"),
511
510
  label=_("SOA MName"),
@@ -560,7 +559,7 @@ class ZoneImportForm(ZoneTemplateUpdateMixin, NetBoxModelImportForm):
560
559
  required=False,
561
560
  to_field_name="name",
562
561
  error_messages={
563
- "invalid_choice": _("Registrar not found."),
562
+ "invalid_choice": _("Registrar %(value)s not found"),
564
563
  },
565
564
  label=_("Registrar"),
566
565
  )
@@ -573,7 +572,7 @@ class ZoneImportForm(ZoneTemplateUpdateMixin, NetBoxModelImportForm):
573
572
  required=False,
574
573
  to_field_name="contact_id",
575
574
  error_messages={
576
- "invalid_choice": _("Registrant contact ID not found"),
575
+ "invalid_choice": _("Registrant contact ID %(value)s not found"),
577
576
  },
578
577
  label=_("Registrant"),
579
578
  )
@@ -582,7 +581,7 @@ class ZoneImportForm(ZoneTemplateUpdateMixin, NetBoxModelImportForm):
582
581
  required=False,
583
582
  to_field_name="contact_id",
584
583
  error_messages={
585
- "invalid_choice": _("Administrative contact ID not found"),
584
+ "invalid_choice": _("Administrative contact ID %(value)s not found"),
586
585
  },
587
586
  label=_("Administrative Contact"),
588
587
  )
@@ -591,7 +590,7 @@ class ZoneImportForm(ZoneTemplateUpdateMixin, NetBoxModelImportForm):
591
590
  required=False,
592
591
  to_field_name="contact_id",
593
592
  error_messages={
594
- "invalid_choice": _("Technical contact ID not found"),
593
+ "invalid_choice": _("Technical contact ID %(value)s not found"),
595
594
  },
596
595
  label=_("Technical Contact"),
597
596
  )
@@ -675,7 +674,7 @@ class ZoneBulkEditForm(NetBoxModelBulkEditForm):
675
674
  view = DynamicModelChoiceField(
676
675
  queryset=View.objects.all(),
677
676
  required=False,
678
- label=_p("DNS", "View"),
677
+ label=_("View"),
679
678
  )
680
679
  status = forms.ChoiceField(
681
680
  choices=add_blank_choice(ZoneStatusChoices),
@@ -159,7 +159,7 @@ class ZoneTemplateImportForm(NetBoxModelImportForm):
159
159
  required=False,
160
160
  to_field_name="name",
161
161
  error_messages={
162
- "invalid_choice": _("Registrar not found."),
162
+ "invalid_choice": _("Registrar %(value)s not found"),
163
163
  },
164
164
  label=_("Registrar"),
165
165
  )
@@ -168,7 +168,7 @@ class ZoneTemplateImportForm(NetBoxModelImportForm):
168
168
  required=False,
169
169
  to_field_name="contact_id",
170
170
  error_messages={
171
- "invalid_choice": _("Registrant contact ID not found"),
171
+ "invalid_choice": _("Registrant contact ID %(value)s not found"),
172
172
  },
173
173
  label=_("Registrant"),
174
174
  )
@@ -177,7 +177,7 @@ class ZoneTemplateImportForm(NetBoxModelImportForm):
177
177
  required=False,
178
178
  to_field_name="contact_id",
179
179
  error_messages={
180
- "invalid_choice": _("Administrative contact ID not found"),
180
+ "invalid_choice": _("Administrative contact ID %(value)s not found"),
181
181
  },
182
182
  label=_("Administrative Contact"),
183
183
  )
@@ -186,7 +186,7 @@ class ZoneTemplateImportForm(NetBoxModelImportForm):
186
186
  required=False,
187
187
  to_field_name="contact_id",
188
188
  error_messages={
189
- "invalid_choice": _("Technical contact ID not found"),
189
+ "invalid_choice": _("Technical contact ID %(value)s not found"),
190
190
  },
191
191
  label=_("Technical Contact"),
192
192
  )
@@ -195,7 +195,7 @@ class ZoneTemplateImportForm(NetBoxModelImportForm):
195
195
  required=False,
196
196
  to_field_name="contact_id",
197
197
  error_messages={
198
- "invalid_choice": _("Billing contact ID not found"),
198
+ "invalid_choice": _("Billing contact ID %(value)s not found"),
199
199
  },
200
200
  label=_("Billing Contact"),
201
201
  )
Binary file
@@ -19,8 +19,6 @@ from netbox_dns.choices import RecordTypeChoices
19
19
  from netbox_dns.validators import validate_fqdn
20
20
  from netbox_dns.mixins import ObjectModificationMixin
21
21
 
22
- from .record import Record
23
-
24
22
 
25
23
  __all__ = (
26
24
  "NameServer",
@@ -80,7 +78,7 @@ class NameServer(ObjectModificationMixin, ContactsMixin, NetBoxModel):
80
78
  {
81
79
  "name": str(exc),
82
80
  }
83
- ) from None
81
+ )
84
82
 
85
83
  try:
86
84
  validate_fqdn(self.name)
@@ -89,7 +87,7 @@ class NameServer(ObjectModificationMixin, ContactsMixin, NetBoxModel):
89
87
  {
90
88
  "name": exc,
91
89
  }
92
- ) from None
90
+ )
93
91
 
94
92
  super().clean(*args, **kwargs)
95
93
 
@@ -112,10 +110,8 @@ class NameServer(ObjectModificationMixin, ContactsMixin, NetBoxModel):
112
110
 
113
111
  def delete(self, *args, **kwargs):
114
112
  with transaction.atomic():
115
- zones = self.zones.all()
116
- for zone in zones:
117
- Record.objects.filter(
118
- Q(zone=zone),
113
+ for zone in self.zones.all():
114
+ zone.record_set.filter(
119
115
  Q(managed=True),
120
116
  Q(value=f"{self.name}."),
121
117
  Q(type=RecordTypeChoices.NS),
@@ -23,11 +23,6 @@ from netbox_dns.validators import validate_generic_name, validate_record_value
23
23
  from netbox_dns.mixins import ObjectModificationMixin
24
24
  from netbox_dns.choices import RecordTypeChoices, RecordStatusChoices
25
25
 
26
- # +
27
- # This is a hack designed to break cyclic imports between Record and Zone
28
- # -
29
- from netbox_dns.models import zone
30
-
31
26
 
32
27
  __all__ = (
33
28
  "Record",
@@ -105,14 +100,8 @@ class RecordManager(models.Manager.from_queryset(RestrictedQuerySet)):
105
100
  .annotate(
106
101
  active=ExpressionWrapper(
107
102
  Q(
108
- Q(zone__status__in=ZONE_ACTIVE_STATUS_LIST)
109
- & Q(
110
- Q(address_record__isnull=True)
111
- | Q(
112
- address_record__zone__status__in=ZONE_ACTIVE_STATUS_LIST
113
- )
114
- )
115
- & Q(status__in=RECORD_ACTIVE_STATUS_LIST)
103
+ zone__status__in=ZONE_ACTIVE_STATUS_LIST,
104
+ status__in=RECORD_ACTIVE_STATUS_LIST,
116
105
  ),
117
106
  output_field=BooleanField(),
118
107
  )
@@ -269,7 +258,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
269
258
 
270
259
  @property
271
260
  def value_fqdn(self):
272
- if self.type != RecordTypeChoices.CNAME:
261
+ if self.type not in (RecordTypeChoices.CNAME, RecordTypeChoices.NS):
273
262
  return None
274
263
 
275
264
  _zone = dns_name.from_text(self.zone.name)
@@ -331,8 +320,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
331
320
  def ptr_zone(self):
332
321
  if self.type == RecordTypeChoices.A:
333
322
  ptr_zone = (
334
- zone.Zone.objects.filter(
335
- view=self.zone.view,
323
+ self.zone.view.zone_set.filter(
336
324
  rfc2317_prefix__net_contains=self.value,
337
325
  )
338
326
  .order_by("rfc2317_prefix__net_mask_length")
@@ -343,15 +331,17 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
343
331
  return ptr_zone
344
332
 
345
333
  ptr_zone = (
346
- zone.Zone.objects.filter(
347
- view=self.zone.view, arpa_network__net_contains=self.value
348
- )
334
+ self.zone.view.zone_set.filter(arpa_network__net_contains=self.value)
349
335
  .order_by("arpa_network__net_mask_length")
350
336
  .last()
351
337
  )
352
338
 
353
339
  return ptr_zone
354
340
 
341
+ @property
342
+ def is_delegation_record(self):
343
+ return self in self.zone.delegation_records
344
+
355
345
  def update_ptr_record(self, update_rfc2317_cname=True, save_zone_serial=True):
356
346
  ptr_zone = self.ptr_zone
357
347
 
@@ -461,10 +451,9 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
461
451
 
462
452
  self.remove_from_rfc2317_cname_record(save_zone_serial=save_zone_serial)
463
453
 
464
- rfc2317_cname_record = Record.objects.filter(
454
+ rfc2317_cname_record = self.zone.rfc2317_parent_zone.record_set.filter(
465
455
  name=cname_name,
466
456
  type=RecordTypeChoices.CNAME,
467
- zone=self.zone.rfc2317_parent_zone,
468
457
  managed=True,
469
458
  value=self.fqdn,
470
459
  ).first()
@@ -612,8 +601,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
612
601
  if new_zone is None:
613
602
  new_zone = self.zone
614
603
 
615
- records = Record.objects.filter(
616
- zone=new_zone,
604
+ records = new_zone.record_set.filter(
617
605
  name=self.name,
618
606
  type=self.type,
619
607
  value=self.value,
@@ -649,8 +637,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
649
637
  if not get_plugin_config("netbox_dns", "dnssync_conflict_deactivate", False):
650
638
  return
651
639
 
652
- records = Record.objects.filter(
653
- zone=self.zone,
640
+ records = self.zone.record_set.filter(
654
641
  name=self.name,
655
642
  type=self.type,
656
643
  value=self.value,
@@ -678,8 +665,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
678
665
  return
679
666
 
680
667
  records = (
681
- Record.objects.filter(
682
- zone=self.zone,
668
+ self.zone.record_set.filter(
683
669
  name=self.name,
684
670
  type=self.type,
685
671
  )
@@ -722,8 +708,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
722
708
  ttl = self.ttl
723
709
 
724
710
  records = (
725
- Record.objects.filter(
726
- zone=self.zone,
711
+ self.zone.record_set.filter(
727
712
  name=self.name,
728
713
  type=self.type,
729
714
  )
@@ -751,9 +736,9 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
751
736
  if not self.is_active:
752
737
  return
753
738
 
754
- records = Record.objects.filter(
755
- name=self.name, zone=self.zone, active=True
756
- ).exclude(pk=self.pk)
739
+ records = self.zone.record_set.filter(name=self.name, active=True).exclude(
740
+ pk=self.pk
741
+ )
757
742
 
758
743
  if self.type == RecordTypeChoices.A and not self.disable_ptr:
759
744
  ptr_zone = self.ptr_zone
@@ -770,8 +755,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
770
755
  )
771
756
 
772
757
  if (
773
- Record.objects.filter(
774
- zone=ptr_cname_zone,
758
+ ptr_cname_zone.record_set.filter(
775
759
  name=ptr_cname_name,
776
760
  active=True,
777
761
  )
@@ -133,17 +133,17 @@ class RecordTemplate(NetBoxModel):
133
133
  {
134
134
  "record_name": exc,
135
135
  }
136
- ) from None
136
+ )
137
137
 
138
138
  def validate_value(self):
139
139
  try:
140
140
  validate_record_value(self)
141
141
  except ValidationError as exc:
142
- raise ValidationError({"value": exc}) from None
142
+ raise ValidationError({"value": exc})
143
143
 
144
144
  def matching_records(self, zone):
145
- return Record.objects.filter(
146
- zone=zone, name=self.record_name, type=self.type, value=self.value
145
+ return zone.record_set.filter(
146
+ name=self.record_name, type=self.type, value=self.value
147
147
  )
148
148
 
149
149
  def create_record(self, zone):
netbox_dns/models/view.py CHANGED
@@ -2,7 +2,6 @@ from django.db import models
2
2
  from django.urls import reverse
3
3
  from django.core.exceptions import ValidationError
4
4
  from django.utils.translation import gettext_lazy as _
5
- from django.utils.translation import pgettext_lazy as _p
6
5
 
7
6
  from netbox.models import NetBoxModel
8
7
  from netbox.models.features import ContactsMixin
@@ -77,8 +76,8 @@ class View(ObjectModificationMixin, ContactsMixin, NetBoxModel):
77
76
  return str(self.name)
78
77
 
79
78
  class Meta:
80
- verbose_name = _p("DNS", "View")
81
- verbose_name_plural = _p("DNS", "Views")
79
+ verbose_name = _("View")
80
+ verbose_name_plural = _("Views")
82
81
 
83
82
  ordering = ("name",)
84
83