Fixes #16782: Add object filtering for custom fields

This commit is contained in:
Sam King 2024-07-23 14:38:19 +10:00
parent e62a42286a
commit ee35388ca3
7 changed files with 38 additions and 4 deletions

View File

@ -74,6 +74,8 @@ If a default value is specified for a selection field, it must exactly match one
An object or multi-object custom field can be used to refer to a particular NetBox object or objects as the "value" for a custom field. These custom fields must define an `object_type`, which determines the type of object to which custom field instances point.
By default, an object choice field will make all objects of that type available for selection in the drop-down. The list choices can be filtered to only show objects with certain values by providing a `query_params` dict in the Related Object Filter field, as a JSON value. More information about `query_params` can be found [here](./custom-scripts.md#objectvar)
## Custom Fields in Templates
Several features within NetBox, such as export templates and webhooks, utilize Jinja2 templating. For convenience, objects which support custom field assignment expose custom field data through the `cf` property. This is a bit cleaner than accessing custom field data through the actual field (`custom_field_data`).

View File

@ -62,7 +62,7 @@ class CustomFieldSerializer(ValidatedModelSerializer):
fields = [
'id', 'url', 'display_url', 'display', 'object_types', 'type', 'related_object_type', 'data_type',
'name', 'label', 'group_name', 'description', 'required', 'search_weight', 'filter_logic', 'ui_visible',
'ui_editable', 'is_cloneable', 'default', 'weight', 'validation_minimum', 'validation_maximum',
'ui_editable', 'is_cloneable', 'default', 'related_object_filter', 'weight', 'validation_minimum', 'validation_maximum',
'validation_regex', 'validation_unique', 'choice_set', 'comments', 'created', 'last_updated',
]
brief_fields = ('id', 'url', 'display', 'name', 'description')

View File

@ -67,7 +67,7 @@ class CustomFieldForm(forms.ModelForm):
FieldSet(
'search_weight', 'filter_logic', 'ui_visible', 'ui_editable', 'weight', 'is_cloneable', name=_('Behavior')
),
FieldSet('default', 'choice_set', name=_('Values')),
FieldSet('default', 'choice_set', 'related_object_filter', name=_('Values')),
FieldSet(
'validation_minimum', 'validation_maximum', 'validation_regex', 'validation_unique', name=_('Validation')
),

View File

@ -0,0 +1,18 @@
# Generated by Django 5.0.7 on 2024-07-19 07:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('extras', '0115_convert_dashboard_widgets'),
]
operations = [
migrations.AddField(
model_name='customfield',
name='related_object_filter',
field=models.JSONField(blank=True, null=True),
),
]

View File

@ -154,6 +154,14 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
'Default value for the field (must be a JSON value). Encapsulate strings with double quotes (e.g. "Foo").'
)
)
related_object_filter = models.JSONField(
blank=True,
null=True,
help_text=_(
'Filter the object selection choices using a query_params dict (must be a JSON value).'
'Encapsulate strings with double quotes (e.g. "Foo").'
)
)
weight = models.PositiveSmallIntegerField(
default=100,
verbose_name=_('display weight'),
@ -511,7 +519,8 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
field = field_class(
queryset=model.objects.all(),
required=required,
initial=initial
initial=initial,
query_params=self.related_object_filter
)
# Multiple objects
@ -522,6 +531,7 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
queryset=model.objects.all(),
required=required,
initial=initial,
query_params=self.related_object_filter
)
# Text

View File

@ -23,7 +23,7 @@ from virtualization.models import Cluster, ClusterGroup, ClusterType
class CustomFieldTestCase(TestCase, ChangeLoggedFilterSetTests):
queryset = CustomField.objects.all()
filterset = CustomFieldFilterSet
ignore_fields = ('default',)
ignore_fields = ('default', 'related_object_filter')
@classmethod
def setUpTestData(cls):

View File

@ -52,6 +52,10 @@
<th scope="row">{% trans "Default Value" %}</th>
<td>{{ object.default }}</td>
</tr>
<tr>
<th scope="row">{% trans "Related object filter" %}</th>
<td>{{ object.related_object_filter }}</td>
</tr>
</table>
</div>
<div class="card">