Compare commits

...

6 Commits

Author SHA1 Message Date
Jeremy Stretch
ebf8f7fa1b Closes #20068: Enable defining profile attributes when importing module types 2025-12-02 16:50:59 -05:00
github-actions
922b08c0ff Update source translation strings
Some checks failed
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Has been cancelled
2025-12-02 05:02:22 +00:00
Bapths
84864fa5e1 Closes #20860: Add changlog message support for component object creation (#20898)
Some checks failed
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Waiting to run
CI / build (20.x, 3.10) (push) Has been cancelled
CI / build (20.x, 3.11) (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled
2025-12-01 17:04:21 -06:00
Jeremy Stretch
767dfccd8f Fixes #20888: Pass decimal values for min/max on latitude and longitude fields (#20892)
Some checks are pending
CI / build (20.x, 3.10) (push) Waiting to run
CI / build (20.x, 3.11) (push) Waiting to run
CI / build (20.x, 3.12) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Waiting to run
2025-12-01 10:35:44 -08:00
Tom Gamull
dc4bab7477 docs: fix broken bookmarks link in model features table
Some checks failed
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Has been cancelled
The bookmarks link was pointing to ../features/customization.md#bookmarks
but the bookmarks section is actually in ../features/user-preferences.md#bookmarks.

This fixes the broken anchor link.
2025-11-26 15:12:52 -05:00
github-actions
60aa952eb1 Update source translation strings
Some checks are pending
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Waiting to run
2025-11-26 05:02:03 +00:00
7 changed files with 330 additions and 283 deletions

View File

@@ -12,7 +12,7 @@ Depending on its classification, each NetBox model may support various features
| Feature | Feature Mixin | Registry Key | Description |
|------------------------------------------------------------|-------------------------|---------------------|-----------------------------------------------------------------------------------------|
| [Bookmarks](../features/customization.md#bookmarks) | `BookmarksMixin` | `bookmarks` | These models can be bookmarked natively in the user interface |
| [Bookmarks](../features/user-preferences.md#bookmarks) | `BookmarksMixin` | `bookmarks` | These models can be bookmarked natively in the user interface |
| [Change logging](../features/change-logging.md) | `ChangeLoggingMixin` | `change_logging` | Changes to these objects are automatically recorded in the change log |
| Cloning | `CloningMixin` | `cloning` | Provides the `clone()` method to prepare a copy |
| [Contacts](../features/contacts.md) | `ContactsMixin` | `contacts` | Contacts can be associated with these models |

View File

@@ -472,14 +472,30 @@ class ModuleTypeImportForm(NetBoxModelImportForm):
required=False,
help_text=_('Unit for module weight')
)
attribute_data = forms.JSONField(
label=_('Attributes'),
required=False,
help_text=_('Attribute values for the assigned profile, passed as a dictionary')
)
class Meta:
model = ModuleType
fields = [
'manufacturer', 'model', 'part_number', 'description', 'airflow', 'weight', 'weight_unit', 'profile',
'comments', 'tags'
'attribute_data', 'comments', 'tags',
]
def clean(self):
super().clean()
# Attribute data may be included only if a profile is specified
if self.cleaned_data.get('attribute_data') and not self.cleaned_data.get('profile'):
raise forms.ValidationError(_("Profile must be specified if attribute data is provided."))
# Default attribute_data to an empty dictionary if a profile is specified (to enforce schema validation)
if self.cleaned_data.get('profile') and not self.cleaned_data.get('attribute_data'):
self.cleaned_data['attribute_data'] = {}
class DeviceRoleImportForm(NetBoxModelImportForm):
parent = CSVModelChoiceField(

View File

@@ -1,3 +1,5 @@
import decimal
import django.core.validators
from django.db import migrations, models
@@ -17,8 +19,8 @@ class Migration(migrations.Migration):
max_digits=8,
null=True,
validators=[
django.core.validators.MinValueValidator(-90.0),
django.core.validators.MaxValueValidator(90.0),
django.core.validators.MinValueValidator(decimal.Decimal('-90.0')),
django.core.validators.MaxValueValidator(decimal.Decimal('90.0'))
],
),
),
@@ -31,8 +33,8 @@ class Migration(migrations.Migration):
max_digits=9,
null=True,
validators=[
django.core.validators.MinValueValidator(-180.0),
django.core.validators.MaxValueValidator(180.0),
django.core.validators.MinValueValidator(decimal.Decimal('-180.0')),
django.core.validators.MaxValueValidator(decimal.Decimal('180.0'))
],
),
),
@@ -45,8 +47,8 @@ class Migration(migrations.Migration):
max_digits=8,
null=True,
validators=[
django.core.validators.MinValueValidator(-90.0),
django.core.validators.MaxValueValidator(90.0),
django.core.validators.MinValueValidator(decimal.Decimal('-90.0')),
django.core.validators.MaxValueValidator(decimal.Decimal('90.0'))
],
),
),
@@ -59,8 +61,8 @@ class Migration(migrations.Migration):
max_digits=9,
null=True,
validators=[
django.core.validators.MinValueValidator(-180.0),
django.core.validators.MaxValueValidator(180.0),
django.core.validators.MinValueValidator(decimal.Decimal('-180.0')),
django.core.validators.MaxValueValidator(decimal.Decimal('180.0'))
],
),
),

View File

@@ -646,7 +646,10 @@ class Device(
decimal_places=6,
blank=True,
null=True,
validators=[MinValueValidator(-90.0), MaxValueValidator(90.0)],
validators=[
MinValueValidator(decimal.Decimal('-90.0')),
MaxValueValidator(decimal.Decimal('90.0'))
],
help_text=_("GPS coordinate in decimal format (xx.yyyyyy)")
)
longitude = models.DecimalField(
@@ -655,7 +658,10 @@ class Device(
decimal_places=6,
blank=True,
null=True,
validators=[MinValueValidator(-180.0), MaxValueValidator(180.0)],
validators=[
MinValueValidator(decimal.Decimal('-180.0')),
MaxValueValidator(decimal.Decimal('180.0'))
],
help_text=_("GPS coordinate in decimal format (xx.yyyyyy)")
)
services = GenericRelation(

View File

@@ -1,3 +1,5 @@
import decimal
from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
@@ -211,7 +213,10 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
decimal_places=6,
blank=True,
null=True,
validators=[MinValueValidator(-90.0), MaxValueValidator(90.0)],
validators=[
MinValueValidator(decimal.Decimal('-90.0')),
MaxValueValidator(decimal.Decimal('90.0'))
],
help_text=_('GPS coordinate in decimal format (xx.yyyyyy)')
)
longitude = models.DecimalField(
@@ -220,7 +225,10 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
decimal_places=6,
blank=True,
null=True,
validators=[MinValueValidator(-180.0), MaxValueValidator(180.0)],
validators=[
MinValueValidator(decimal.Decimal('-180.0')),
MaxValueValidator(decimal.Decimal('180.0'))
],
help_text=_('GPS coordinate in decimal format (xx.yyyyyy)')
)

View File

@@ -559,6 +559,7 @@ class ComponentCreateView(GetReturnURLMixin, BaseObjectView):
form.instance._replicated_base = hasattr(self.form, "replication_fields")
if form.is_valid():
changelog_message = form.cleaned_data.pop('changelog_message', '')
new_components = []
data = deepcopy(request.POST)
pattern_count = len(form.cleaned_data[self.form.replication_fields[0]])
@@ -585,6 +586,9 @@ class ComponentCreateView(GetReturnURLMixin, BaseObjectView):
# Create the new components
new_objs = []
for component_form in new_components:
# Record changelog message (if any)
if changelog_message:
component_form.instance._changelog_message = changelog_message
obj = component_form.save()
new_objs.append(obj)

File diff suppressed because it is too large Load Diff