Skip to content

Commit a4f9dcf

Browse files
committed
feat(models): Add internationalization support
Introduces internationalization (i18n) to AccessList models. Updates field definitions to use `gettext_lazy` for translations and improves model class field consistency. Includes minor corrections to docstrings and comments.
1 parent ed73288 commit a4f9dcf

File tree

2 files changed

+81
-74
lines changed

2 files changed

+81
-74
lines changed

netbox_acls/models/access_list_rules.py

Lines changed: 61 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
Define the django models for this plugin.
33
"""
44

5-
from django.apps import apps
65
from django.contrib.postgres.fields import ArrayField
76
from django.db import models
87
from django.urls import reverse
8+
from django.utils.translation import gettext_lazy as _
99
from netbox.models import NetBoxModel
1010

1111
from ..choices import ACLProtocolChoices, ACLRuleActionChoices, ACLTypeChoices
@@ -21,48 +21,42 @@
2121
class ACLRule(NetBoxModel):
2222
"""
2323
Abstract model for ACL Rules.
24-
Inherrited by both ACLStandardRule and ACLExtendedRule.
24+
Inherited by both ACLStandardRule and ACLExtendedRule.
2525
"""
2626

2727
access_list = models.ForeignKey(
28-
on_delete=models.CASCADE,
2928
to=AccessList,
30-
verbose_name="Access List",
29+
on_delete=models.CASCADE,
3130
related_name="rules",
31+
verbose_name=_("Access List"),
3232
)
3333
index = models.PositiveIntegerField()
3434
remark = models.CharField(
35+
verbose_name=_("Remark"),
3536
max_length=500,
3637
blank=True,
3738
)
3839
description = models.CharField(
40+
verbose_name=_("Description"),
3941
max_length=500,
4042
blank=True,
4143
)
4244
action = models.CharField(
43-
choices=ACLRuleActionChoices,
45+
verbose_name=_("Action"),
4446
max_length=30,
47+
choices=ACLRuleActionChoices,
4548
)
4649
source_prefix = models.ForeignKey(
47-
blank=True,
48-
null=True,
50+
to="ipam.prefix",
4951
on_delete=models.PROTECT,
5052
related_name="+",
51-
to="ipam.Prefix",
52-
verbose_name="Source Prefix",
53+
verbose_name=_("Source Prefix"),
54+
blank=True,
55+
null=True,
5356
)
5457

5558
clone_fields = ("access_list", "action", "source_prefix")
56-
57-
def __str__(self):
58-
return f"{self.access_list}: Rule {self.index}"
59-
60-
def get_action_color(self):
61-
return ACLRuleActionChoices.colors.get(self.action)
62-
63-
@classmethod
64-
def get_prerequisite_models(cls):
65-
return [apps.get_model("ipam.Prefix"), AccessList]
59+
prerequisite_models = ("netbox_acls.AccessList",)
6660

6761
class Meta:
6862
"""
@@ -76,31 +70,36 @@ class Meta:
7670
ordering = ["access_list", "index"]
7771
unique_together = ["access_list", "index"]
7872

73+
def __str__(self):
74+
return f"{self.access_list}: Rule {self.index}"
75+
76+
def get_absolute_url(self):
77+
"""
78+
The method is a Django convention; although not strictly required,
79+
it conveniently returns the absolute URL for any particular object.
80+
"""
81+
return reverse(
82+
f"plugins:{self._meta.app_label}:{self._meta.model_name}",
83+
args=[self.pk],
84+
)
85+
86+
def get_action_color(self):
87+
return ACLRuleActionChoices.colors.get(self.action)
88+
7989

8090
class ACLStandardRule(ACLRule):
8191
"""
8292
Inherits ACLRule.
8393
"""
8494

8595
access_list = models.ForeignKey(
86-
on_delete=models.CASCADE,
8796
to=AccessList,
88-
verbose_name="Standard Access List",
89-
limit_choices_to={"type": ACLTypeChoices.TYPE_STANDARD},
97+
on_delete=models.CASCADE,
9098
related_name="aclstandardrules",
99+
limit_choices_to={"type": ACLTypeChoices.TYPE_STANDARD},
100+
verbose_name=_("Standard Access List"),
91101
)
92102

93-
def get_absolute_url(self):
94-
"""
95-
The method is a Django convention; although not strictly required,
96-
it conveniently returns the absolute URL for any particular object.
97-
"""
98-
return reverse("plugins:netbox_acls:aclstandardrule", args=[self.pk])
99-
100-
@classmethod
101-
def get_prerequisite_models(cls):
102-
return [AccessList]
103-
104103
class Meta(ACLRule.Meta):
105104
"""
106105
Define the model properties adding to or overriding the inherited class:
@@ -109,62 +108,59 @@ class Meta(ACLRule.Meta):
109108
- verbose name plural (for displaying in the GUI)
110109
"""
111110

112-
verbose_name = "ACL Standard Rule"
113-
verbose_name_plural = "ACL Standard Rules"
111+
verbose_name = _("ACL Standard Rule")
112+
verbose_name_plural = _("ACL Standard Rules")
114113

115114

116115
class ACLExtendedRule(ACLRule):
117116
"""
118117
Inherits ACLRule.
119-
Add ACLExtendedRule specific fields: source_ports, desintation_prefix, destination_ports, and protocol
118+
Add ACLExtendedRule specific fields: source_ports, destination_prefix, destination_ports, and protocol
120119
"""
121120

122121
access_list = models.ForeignKey(
123-
on_delete=models.CASCADE,
124122
to=AccessList,
125-
verbose_name="Extended Access List",
126-
limit_choices_to={"type": "extended"},
123+
on_delete=models.CASCADE,
127124
related_name="aclextendedrules",
125+
limit_choices_to={"type": "extended"},
126+
verbose_name=_("Extended Access List"),
128127
)
129128
source_ports = ArrayField(
130129
base_field=models.PositiveIntegerField(),
130+
verbose_name=_("Source Ports"),
131131
blank=True,
132132
null=True,
133-
verbose_name="Soure Ports",
134133
)
135134
destination_prefix = models.ForeignKey(
136-
blank=True,
137-
null=True,
135+
to="ipam.prefix",
138136
on_delete=models.PROTECT,
139137
related_name="+",
140-
to="ipam.Prefix",
141-
verbose_name="Destination Prefix",
138+
verbose_name=_("Destination Prefix"),
139+
blank=True,
140+
null=True,
142141
)
143142
destination_ports = ArrayField(
144143
base_field=models.PositiveIntegerField(),
144+
verbose_name=_("Destination Ports"),
145145
blank=True,
146146
null=True,
147-
verbose_name="Destination Ports",
148147
)
149148
protocol = models.CharField(
150-
blank=True,
151-
choices=ACLProtocolChoices,
149+
verbose_name=_("Protocol"),
152150
max_length=30,
151+
choices=ACLProtocolChoices,
152+
blank=True,
153153
)
154154

155-
def get_absolute_url(self):
156-
"""
157-
The method is a Django convention; although not strictly required,
158-
it conveniently returns the absolute URL for any particular object.
159-
"""
160-
return reverse("plugins:netbox_acls:aclextendedrule", args=[self.pk])
161-
162-
def get_protocol_color(self):
163-
return ACLProtocolChoices.colors.get(self.protocol)
164-
165-
@classmethod
166-
def get_prerequisite_models(cls):
167-
return [apps.get_model("ipam.Prefix"), AccessList]
155+
clone_fields = (
156+
"access_list",
157+
"action",
158+
"source_prefix",
159+
"source_ports",
160+
"destination_prefix",
161+
"destination_ports",
162+
"protocol",
163+
)
168164

169165
class Meta(ACLRule.Meta):
170166
"""
@@ -174,5 +170,8 @@ class Meta(ACLRule.Meta):
174170
- verbose name plural (for displaying in the GUI)
175171
"""
176172

177-
verbose_name = "ACL Extended Rule"
178-
verbose_name_plural = "ACL Extended Rules"
173+
verbose_name = _("ACL Extended Rule")
174+
verbose_name_plural = _("ACL Extended Rules")
175+
176+
def get_protocol_color(self):
177+
return ACLProtocolChoices.colors.get(self.protocol)

netbox_acls/models/access_lists.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from django.core.validators import RegexValidator
99
from django.db import models
1010
from django.urls import reverse
11+
from django.utils.translation import gettext_lazy as _
1112
from netbox.models import NetBoxModel
1213
from virtualization.models import VirtualMachine, VMInterface
1314

@@ -22,7 +23,7 @@
2223

2324
alphanumeric_plus = RegexValidator(
2425
r"^[a-zA-Z0-9-_]+$",
25-
"Only alphanumeric, hyphens, and underscores characters are allowed.",
26+
_("Only alphanumeric, hyphens, and underscores characters are allowed."),
2627
)
2728

2829

@@ -32,43 +33,47 @@ class AccessList(NetBoxModel):
3233
"""
3334

3435
name = models.CharField(
36+
verbose_name=_("Name"),
3537
max_length=500,
3638
validators=[alphanumeric_plus],
3739
)
3840
assigned_object_type = models.ForeignKey(
3941
to=ContentType,
40-
limit_choices_to=ACL_HOST_ASSIGNMENT_MODELS,
4142
on_delete=models.PROTECT,
43+
related_name="+",
44+
limit_choices_to=ACL_HOST_ASSIGNMENT_MODELS,
45+
verbose_name=_("Assigned Object Type"),
4246
)
4347
assigned_object_id = models.PositiveBigIntegerField()
4448
assigned_object = GenericForeignKey(
4549
ct_field="assigned_object_type",
4650
fk_field="assigned_object_id",
4751
)
4852
type = models.CharField(
53+
verbose_name=_("Type"),
4954
max_length=30,
5055
choices=ACLTypeChoices,
5156
)
5257
default_action = models.CharField(
53-
default=ACLActionChoices.ACTION_DENY,
58+
verbose_name=_("Default Action"),
5459
max_length=30,
60+
default=ACLActionChoices.ACTION_DENY,
5561
choices=ACLActionChoices,
56-
verbose_name="Default Action",
5762
)
5863
comments = models.TextField(
5964
blank=True,
6065
)
6166

6267
clone_fields = (
63-
"type",
6468
"default_action",
69+
"type",
6570
)
6671

6772
class Meta:
6873
unique_together = ["assigned_object_type", "assigned_object_id", "name"]
6974
ordering = ["assigned_object_type", "assigned_object_id", "name"]
70-
verbose_name = "Access List"
71-
verbose_name_plural = "Access Lists"
75+
verbose_name = _("Access List")
76+
verbose_name_plural = _("Access Lists")
7277

7378
def __str__(self):
7479
return self.name
@@ -95,18 +100,21 @@ class ACLInterfaceAssignment(NetBoxModel):
95100
"""
96101

97102
access_list = models.ForeignKey(
98-
on_delete=models.CASCADE,
99103
to=AccessList,
100-
verbose_name="Access List",
104+
on_delete=models.CASCADE,
105+
verbose_name=_("Access List"),
101106
)
102107
direction = models.CharField(
108+
verbose_name=_("Direction"),
103109
max_length=30,
104110
choices=ACLAssignmentDirectionChoices,
105111
)
106112
assigned_object_type = models.ForeignKey(
107113
to=ContentType,
108-
limit_choices_to=ACL_INTERFACE_ASSIGNMENT_MODELS,
109114
on_delete=models.PROTECT,
115+
related_name="+",
116+
limit_choices_to=ACL_INTERFACE_ASSIGNMENT_MODELS,
117+
verbose_name=_("Assigned Object Type"),
110118
)
111119
assigned_object_id = models.PositiveBigIntegerField()
112120
assigned_object = GenericForeignKey(
@@ -133,8 +141,8 @@ class Meta:
133141
"access_list",
134142
"direction",
135143
]
136-
verbose_name = "ACL Interface Assignment"
137-
verbose_name_plural = "ACL Interface Assignments"
144+
verbose_name = _("ACL Interface Assignment")
145+
verbose_name_plural = _("ACL Interface Assignments")
138146

139147
def __str__(self):
140148
return f"{self.access_list}: Interface {self.assigned_object}"

0 commit comments

Comments
 (0)