Compare commits

...

3 Commits

Author SHA1 Message Date
Martin Hauser
83bb19a7b4 fix(dcim): Handle missing Virtual Circuit Termination gracefully
Replace direct attribute access with try-except to catch
ObjectDoesNotExist when virtual_circuit_termination relation is missing.
Prevents errors when rendering Virtual Circuits Panel with broken or
missing terminations.

Fixes #21808
2026-04-01 13:47:11 +02:00
github-actions
2563122352 Update source translation strings 2026-04-01 05:39:05 +00:00
Martin Hauser
0455e14c29 docs(plugins): Use @register_search in plugin search docs
Align the plugin search example with the recommended registration
pattern used in the general search documentation and NetBox core.

Replace the legacy `indexes = [...]` example with decorator-based
registration to make the preferred approach clearer for plugin authors.
2026-03-31 16:55:27 -04:00
3 changed files with 370 additions and 487 deletions

View File

@@ -1,12 +1,14 @@
# Search
Plugins can define and register their own models to extend NetBox's core search functionality. Typically, a plugin will include a file named `search.py`, which holds all search indexes for its models (see the example below).
Plugins can define and register their own models to extend NetBox's core search functionality. Typically, a plugin will include a file named `search.py`, which holds all search indexes for its models.
```python
```python title="search.py"
# search.py
from netbox.search import SearchIndex
from netbox.search import SearchIndex, register_search
from .models import MyModel
@register_search
class MyModelIndex(SearchIndex):
model = MyModel
fields = (
@@ -17,15 +19,11 @@ class MyModelIndex(SearchIndex):
display_attrs = ('site', 'device', 'status', 'description')
```
Fields listed in `display_attrs` will not be cached for search, but will be displayed alongside the object when it appears in global search results. This is helpful for conveying to the user additional information about an object.
Decorate each `SearchIndex` subclass with `@register_search` to register it with NetBox. When using the default `search.py` module, no additional `indexes = [...]` list is required.
To register one or more indexes with NetBox, define a list named `indexes` at the end of this file:
```python
indexes = [MyModelIndex]
```
Fields listed in `display_attrs` are not cached for matching, but they are displayed alongside the object in global search results to provide additional context.
!!! tip
The path to the list of search indexes can be modified by setting `search_indexes` in the PluginConfig instance.
The legacy `indexes = [...]` list remains supported via `PluginConfig.search_indexes` for backward compatibility and custom loading patterns.
::: netbox.search.SearchIndex

View File

@@ -1,4 +1,5 @@
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _
@@ -532,8 +533,14 @@ class VirtualCircuitPanel(panels.ObjectPanel):
def render(self, context):
obj = context.get('object')
if not obj or not obj.is_virtual or not obj.virtual_circuit_termination:
if not obj or not obj.is_virtual:
return ''
try:
obj.virtual_circuit_termination
except ObjectDoesNotExist:
return ''
ctx = self.get_context(context)
return render_to_string(self.template_name, ctx, request=ctx.get('request'))

File diff suppressed because it is too large Load Diff