Fixes #19415: Increased Circuit/WirelessLink distance upper limit (#19495)

* Fixes #19415: Increased Circuit/WirelessLink absolute distance upper limit

Also adds form validation that provides a useful message to the user
rather than a 500 error with potentially little information.

* Include forgotten migration files

* Remove unnecessary comments

* Remove more unnecessary comments

* Addresses PR feedback

* Gah, remove django migration header comment

* Clean up new has_field_errors mechanism, fix issue with ObjectAttribute

* Address PR feedback, revert changes to render_fieldset template tag
This commit is contained in:
Jason Novinger 2025-05-19 07:38:30 -05:00 committed by GitHub
parent 03ff535772
commit a2a8779ebc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 57 additions and 4 deletions

View File

@ -16,6 +16,7 @@ from utilities.forms import get_field_value
from utilities.forms.fields import ( from utilities.forms.fields import (
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField, CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField,
) )
from utilities.forms.mixins import DistanceValidationMixin
from utilities.forms.rendering import FieldSet, InlineFields from utilities.forms.rendering import FieldSet, InlineFields
from utilities.forms.widgets import DatePicker, HTMXSelect, NumberWithOptions from utilities.forms.widgets import DatePicker, HTMXSelect, NumberWithOptions
from utilities.templatetags.builtins.filters import bettertitle from utilities.templatetags.builtins.filters import bettertitle
@ -105,7 +106,7 @@ class CircuitTypeForm(NetBoxModelForm):
] ]
class CircuitForm(TenancyForm, NetBoxModelForm): class CircuitForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm):
provider = DynamicModelChoiceField( provider = DynamicModelChoiceField(
label=_('Provider'), label=_('Provider'),
queryset=Provider.objects.all(), queryset=Provider.objects.all(),

View File

@ -0,0 +1,16 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('circuits', '0051_virtualcircuit_group_assignment'),
]
operations = [
migrations.AlterField(
model_name='circuit',
name='_abs_distance',
field=models.DecimalField(blank=True, decimal_places=4, max_digits=13, null=True),
),
]

View File

@ -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.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from netbox.choices import * from netbox.choices import *
from utilities.conversion import to_grams, to_meters from utilities.conversion import to_grams, to_meters
@ -58,7 +59,7 @@ class DistanceMixin(models.Model):
max_digits=8, max_digits=8,
decimal_places=2, decimal_places=2,
blank=True, blank=True,
null=True null=True,
) )
distance_unit = models.CharField( distance_unit = models.CharField(
verbose_name=_('distance unit'), verbose_name=_('distance unit'),
@ -69,7 +70,7 @@ class DistanceMixin(models.Model):
) )
# Stores the normalized distance (in meters) for database ordering # Stores the normalized distance (in meters) for database ordering
_abs_distance = models.DecimalField( _abs_distance = models.DecimalField(
max_digits=10, max_digits=13,
decimal_places=4, decimal_places=4,
blank=True, blank=True,
null=True null=True

View File

@ -1,10 +1,13 @@
import time import time
from decimal import Decimal
from django import forms from django import forms
from django.core.validators import MaxValueValidator, MinValueValidator
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
__all__ = ( __all__ = (
'CheckLastUpdatedMixin', 'CheckLastUpdatedMixin',
'DistanceValidationMixin',
) )
@ -44,3 +47,13 @@ class CheckLastUpdatedMixin(forms.Form):
"This object has been modified since the form was rendered. Please consult the object's change " "This object has been modified since the form was rendered. Please consult the object's change "
"log for details." "log for details."
)) ))
class DistanceValidationMixin(forms.Form):
distance = forms.DecimalField(
required=False,
validators=[
MinValueValidator(Decimal(0)),
MaxValueValidator(Decimal(100000)),
]
)

View File

@ -31,6 +31,11 @@
<div class="col mb-1"> <div class="col mb-1">
{{ field }} {{ field }}
<div class="form-text">{% trans field.label %}</div> <div class="form-text">{% trans field.label %}</div>
{% if field.errors %}
<div class="form-text text-danger">
{% for error in field.errors %}{{ error }}{% if not forloop.last %}<br />{% endif %}{% endfor %}
</div>
{% endif %}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>

View File

@ -7,6 +7,7 @@ from ipam.models import VLAN
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from utilities.forms.fields import CommentField, DynamicModelChoiceField, SlugField from utilities.forms.fields import CommentField, DynamicModelChoiceField, SlugField
from utilities.forms.mixins import DistanceValidationMixin
from utilities.forms.rendering import FieldSet, InlineFields from utilities.forms.rendering import FieldSet, InlineFields
from wireless.models import * from wireless.models import *
@ -73,7 +74,7 @@ class WirelessLANForm(ScopedForm, TenancyForm, NetBoxModelForm):
} }
class WirelessLinkForm(TenancyForm, NetBoxModelForm): class WirelessLinkForm(DistanceValidationMixin, TenancyForm, NetBoxModelForm):
site_a = DynamicModelChoiceField( site_a = DynamicModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
required=False, required=False,

View File

@ -0,0 +1,16 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wireless', '0014_wirelesslangroup_comments'),
]
operations = [
migrations.AlterField(
model_name='wirelesslink',
name='_abs_distance',
field=models.DecimalField(blank=True, decimal_places=4, max_digits=13, null=True),
),
]