mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-19 20:02:22 -06:00
Merge branch 'feature' into 9856-strawberry-2
This commit is contained in:
@@ -4,7 +4,7 @@ NetBox validates every object prior to it being written to the database to ensur
|
||||
|
||||
## Custom Validation Rules
|
||||
|
||||
Custom validation rules are expressed as a mapping of model attributes to a set of rules to which that attribute must conform. For example:
|
||||
Custom validation rules are expressed as a mapping of object attributes to a set of rules to which that attribute must conform. For example:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -17,6 +17,8 @@ Custom validation rules are expressed as a mapping of model attributes to a set
|
||||
|
||||
This defines a custom validator which checks that the length of the `name` attribute for an object is at least five characters long, and no longer than 30 characters. This validation is executed _after_ NetBox has performed its own internal validation.
|
||||
|
||||
### Validation Types
|
||||
|
||||
The `CustomValidator` class supports several validation types:
|
||||
|
||||
* `min`: Minimum value
|
||||
@@ -34,16 +36,33 @@ The `min` and `max` types should be defined for numeric values, whereas `min_len
|
||||
!!! warning
|
||||
Bear in mind that these validators merely supplement NetBox's own validation: They will not override it. For example, if a certain model field is required by NetBox, setting a validator for it with `{'prohibited': True}` will not work.
|
||||
|
||||
### Validating Request Parameters
|
||||
|
||||
!!! info "This feature was introduced in NetBox v4.0."
|
||||
|
||||
In addition to validating object attributes, custom validators can also match against parameters of the current request (where available). For example, the following rule will permit only the user named "admin" to modify an object:
|
||||
|
||||
```json
|
||||
{
|
||||
"request.user.username": {
|
||||
"eq": "admin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
Custom validation should generally not be used to enforce permissions. NetBox provides a robust [object-based permissions](../administration/permissions.md) mechanism which should be used for this purpose.
|
||||
|
||||
### Custom Validation Logic
|
||||
|
||||
There may be instances where the provided validation types are insufficient. NetBox provides a `CustomValidator` class which can be extended to enforce arbitrary validation logic by overriding its `validate()` method, and calling `fail()` when an unsatisfactory condition is detected.
|
||||
There may be instances where the provided validation types are insufficient. NetBox provides a `CustomValidator` class which can be extended to enforce arbitrary validation logic by overriding its `validate()` method, and calling `fail()` when an unsatisfactory condition is detected. The `validate()` method should accept an instance (the object being saved) as well as the current request effecting the change.
|
||||
|
||||
```python
|
||||
from extras.validators import CustomValidator
|
||||
|
||||
class MyValidator(CustomValidator):
|
||||
|
||||
def validate(self, instance):
|
||||
def validate(self, instance, request):
|
||||
if instance.status == 'active' and not instance.description:
|
||||
self.fail("Active sites must have a description set!", field='status')
|
||||
```
|
||||
|
||||
@@ -62,10 +62,11 @@ class Circuit(PrimaryModel):
|
||||
|
||||
1. Import `gettext_lazy` as `_`.
|
||||
2. All form fields must specify a `label` wrapped with `gettext_lazy()`.
|
||||
3. All headers under a form's `fieldsets` property must be wrapped with `gettext_lazy()`.
|
||||
3. The name of each FieldSet on a form must be wrapped with `gettext_lazy()`.
|
||||
|
||||
```python
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from utilities.forms.rendering import FieldSet
|
||||
|
||||
class CircuitBulkEditForm(NetBoxModelBulkEditForm):
|
||||
description = forms.CharField(
|
||||
@@ -74,7 +75,7 @@ class CircuitBulkEditForm(NetBoxModelBulkEditForm):
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
(_('Circuit'), ('provider', 'type', 'status', 'description')),
|
||||
FieldSet('provider', 'type', 'status', 'description', name=_('Circuit')),
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
@@ -26,3 +26,7 @@ The location's operational status.
|
||||
|
||||
!!! tip
|
||||
Additional statuses may be defined by setting `Location.status` under the [`FIELD_CHOICES`](../../configuration/data-validation.md#field_choices) configuration parameter.
|
||||
|
||||
### Facility
|
||||
|
||||
Data center or facility designation for identifying the location.
|
||||
|
||||
@@ -15,16 +15,18 @@ NetBox provides several base form classes for use by plugins.
|
||||
|
||||
This is the base form for creating and editing NetBox models. It extends Django's ModelForm to add support for tags and custom fields.
|
||||
|
||||
| Attribute | Description |
|
||||
|-------------|-------------------------------------------------------------|
|
||||
| `fieldsets` | A tuple of two-tuples defining the form's layout (optional) |
|
||||
| Attribute | Description |
|
||||
|-------------|---------------------------------------------------------------------------------------|
|
||||
| `fieldsets` | A tuple of `FieldSet` instances which control how form fields are rendered (optional) |
|
||||
|
||||
**Example**
|
||||
|
||||
```python
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from dcim.models import Site
|
||||
from netbox.forms import NetBoxModelForm
|
||||
from utilities.forms.fields import CommentField, DynamicModelChoiceField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from .models import MyModel
|
||||
|
||||
class MyModelForm(NetBoxModelForm):
|
||||
@@ -33,8 +35,8 @@ class MyModelForm(NetBoxModelForm):
|
||||
)
|
||||
comments = CommentField()
|
||||
fieldsets = (
|
||||
('Model Stuff', ('name', 'status', 'site', 'tags')),
|
||||
('Tenancy', ('tenant_group', 'tenant')),
|
||||
FieldSet('name', 'status', 'site', 'tags', name=_('Model Stuff')),
|
||||
FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@@ -52,6 +54,7 @@ This form facilitates the bulk import of new objects from CSV, JSON, or YAML dat
|
||||
**Example**
|
||||
|
||||
```python
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from dcim.models import Site
|
||||
from netbox.forms import NetBoxModelImportForm
|
||||
from utilities.forms import CSVModelChoiceField
|
||||
@@ -62,7 +65,7 @@ class MyModelImportForm(NetBoxModelImportForm):
|
||||
site = CSVModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Assigned site'
|
||||
help_text=_('Assigned site')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@@ -77,16 +80,18 @@ This form facilitates editing multiple objects in bulk. Unlike a model form, thi
|
||||
| Attribute | Description |
|
||||
|-------------------|---------------------------------------------------------------------------------------------|
|
||||
| `model` | The model of object being edited |
|
||||
| `fieldsets` | A tuple of two-tuples defining the form's layout (optional) |
|
||||
| `fieldsets` | A tuple of `FieldSet` instances which control how form fields are rendered (optional) |
|
||||
| `nullable_fields` | A tuple of fields which can be nullified (set to empty) using the bulk edit form (optional) |
|
||||
|
||||
**Example**
|
||||
|
||||
```python
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from dcim.models import Site
|
||||
from netbox.forms import NetBoxModelImportForm
|
||||
from utilities.forms import CommentField, DynamicModelChoiceField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from .models import MyModel, MyModelStatusChoices
|
||||
|
||||
|
||||
@@ -106,7 +111,7 @@ class MyModelEditForm(NetBoxModelImportForm):
|
||||
|
||||
model = MyModel
|
||||
fieldsets = (
|
||||
('Model Stuff', ('name', 'status', 'site')),
|
||||
FieldSet('name', 'status', 'site', name=_('Model Stuff')),
|
||||
)
|
||||
nullable_fields = ('site', 'comments')
|
||||
```
|
||||
@@ -115,10 +120,10 @@ class MyModelEditForm(NetBoxModelImportForm):
|
||||
|
||||
This form class is used to render a form expressly for filtering a list of objects. Its fields should correspond to filters defined on the model's filter set.
|
||||
|
||||
| Attribute | Description |
|
||||
|-------------------|-------------------------------------------------------------|
|
||||
| `model` | The model of object being edited |
|
||||
| `fieldsets` | A tuple of two-tuples defining the form's layout (optional) |
|
||||
| Attribute | Description |
|
||||
|-------------|---------------------------------------------------------------------------------------|
|
||||
| `model` | The model of object being edited |
|
||||
| `fieldsets` | A tuple of `FieldSet` instances which control how form fields are rendered (optional) |
|
||||
|
||||
**Example**
|
||||
|
||||
@@ -206,3 +211,13 @@ In addition to the [form fields provided by Django](https://docs.djangoproject.c
|
||||
::: utilities.forms.fields.CSVMultipleContentTypeField
|
||||
options:
|
||||
members: false
|
||||
|
||||
## Form Rendering
|
||||
|
||||
::: utilities.forms.rendering.FieldSet
|
||||
|
||||
::: utilities.forms.rendering.InlineFields
|
||||
|
||||
::: utilities.forms.rendering.TabbedGroups
|
||||
|
||||
::: utilities.forms.rendering.ObjectAttribute
|
||||
|
||||
@@ -49,8 +49,8 @@ menu_items = (item1, item2, item3)
|
||||
Each menu item represents a link and (optionally) a set of buttons comprising one entry in NetBox's navigation menu. Menu items are defined as PluginMenuItem instances. An example is shown below.
|
||||
|
||||
```python title="navigation.py"
|
||||
from netbox.choices import ButtonColorChoices
|
||||
from netbox.plugins import PluginMenuButton, PluginMenuItem
|
||||
from utilities.choices import ButtonColorChoices
|
||||
|
||||
item1 = PluginMenuItem(
|
||||
link='plugins:myplugin:myview',
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
* The deprecated `device_role` & `device_role_id` filters for devices have been removed. (Use `role` and `role_id` instead.)
|
||||
* The legacy reports functionality has been dropped. Reports will be automatically converted to custom scripts on upgrade.
|
||||
* The `parent` and `parent_id` filters for locations now return only immediate children of the specified location. (Use `ancestor` and `ancestor_id` to return _all_ descendants.)
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -17,18 +18,26 @@ The NetBox user interface has been completely refreshed and updated.
|
||||
|
||||
The REST API now supports specifying which fields to include in the response data.
|
||||
|
||||
#### Advanced FieldSet Functionality ([#14739](https://github.com/netbox-community/netbox/issues/14739))
|
||||
|
||||
New resources have been introduced to enable advanced form rendering without a need for custom HTML templates.
|
||||
|
||||
### Enhancements
|
||||
|
||||
* [#12851](https://github.com/netbox-community/netbox/issues/12851) - Replace bleach HTML sanitization library with nh3
|
||||
* [#13283](https://github.com/netbox-community/netbox/issues/13283) - Display additional context on API-backed dropdown fields
|
||||
* [#13918](https://github.com/netbox-community/netbox/issues/13918) - Add `facility` field to Location model
|
||||
* [#14237](https://github.com/netbox-community/netbox/issues/14237) - Automatically clear dependent selection fields when modifying a parent selection
|
||||
* [#14454](https://github.com/netbox-community/netbox/issues/14454) - Include member devices for virtual chassis in REST API
|
||||
* [#14637](https://github.com/netbox-community/netbox/issues/14637) - Upgrade to Django 5.0
|
||||
* [#14672](https://github.com/netbox-community/netbox/issues/14672) - Add support for Python 3.12
|
||||
* [#14728](https://github.com/netbox-community/netbox/issues/14728) - The plugins list view has been moved from the legacy admin UI to the main NetBox UI
|
||||
* [#14729](https://github.com/netbox-community/netbox/issues/14729) - All background task views have been moved from the legacy admin UI to the main NetBox UI
|
||||
* [#14438](https://github.com/netbox-community/netbox/issues/14438) - Track individual custom scripts as database objects
|
||||
* [#15131](https://github.com/netbox-community/netbox/issues/15131) - Automatically annotate related object counts on REST API querysets
|
||||
* [#15237](https://github.com/netbox-community/netbox/issues/15237) - Ensure consistent filtering ability for all model fields
|
||||
* [#15238](https://github.com/netbox-community/netbox/issues/15238) - Include the `description` field in "brief" REST API serializations
|
||||
* [#15383](https://github.com/netbox-community/netbox/issues/15383) - Standardize filtering logic for the parents of recursively-nested models (parent & ancestor filters)
|
||||
|
||||
### Other Changes
|
||||
|
||||
@@ -44,6 +53,7 @@ The REST API now supports specifying which fields to include in the response dat
|
||||
* [#15042](https://github.com/netbox-community/netbox/issues/15042) - Rearchitect the logic for registering models & model features
|
||||
* [#15099](https://github.com/netbox-community/netbox/issues/15099) - Remove obsolete `device_role` and `device_role_id` filters for devices
|
||||
* [#15100](https://github.com/netbox-community/netbox/issues/15100) - Remove obsolete `NullableCharField` class
|
||||
* [#15193](https://github.com/netbox-community/netbox/issues/15193) - Switch to compiled distribution of the `psycopg` library
|
||||
* [#15277](https://github.com/netbox-community/netbox/issues/15277) - Replace references to ContentType without ObjectType proxy model & standardize field names
|
||||
* [#15292](https://github.com/netbox-community/netbox/issues/15292) - Remove obsolete `device_role` attribute from Device model (this field was renamed to `role` in v3.6)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user