netbox-custom-widget 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. netbox_custom_widget-0.1.0/LICENSE +15 -0
  2. netbox_custom_widget-0.1.0/PKG-INFO +82 -0
  3. netbox_custom_widget-0.1.0/README.md +54 -0
  4. netbox_custom_widget-0.1.0/netbox_custom_widget/__init__.py +93 -0
  5. netbox_custom_widget-0.1.0/netbox_custom_widget/api/__init__.py +0 -0
  6. netbox_custom_widget-0.1.0/netbox_custom_widget/api/serializers.py +40 -0
  7. netbox_custom_widget-0.1.0/netbox_custom_widget/api/urls.py +10 -0
  8. netbox_custom_widget-0.1.0/netbox_custom_widget/api/views.py +15 -0
  9. netbox_custom_widget-0.1.0/netbox_custom_widget/filtersets.py +26 -0
  10. netbox_custom_widget-0.1.0/netbox_custom_widget/forms.py +91 -0
  11. netbox_custom_widget-0.1.0/netbox_custom_widget/migrations/0001_initial.py +132 -0
  12. netbox_custom_widget-0.1.0/netbox_custom_widget/migrations/__init__.py +0 -0
  13. netbox_custom_widget-0.1.0/netbox_custom_widget/models.py +106 -0
  14. netbox_custom_widget-0.1.0/netbox_custom_widget/navigation.py +28 -0
  15. netbox_custom_widget-0.1.0/netbox_custom_widget/tables.py +40 -0
  16. netbox_custom_widget-0.1.0/netbox_custom_widget/templates/netbox_custom_widget/customapiendpoint.html +114 -0
  17. netbox_custom_widget-0.1.0/netbox_custom_widget/templates/netbox_custom_widget/widgets/custom_api.html +24 -0
  18. netbox_custom_widget-0.1.0/netbox_custom_widget/templates/netbox_custom_widget/widgets/custom_api_content.html +68 -0
  19. netbox_custom_widget-0.1.0/netbox_custom_widget/urls.py +68 -0
  20. netbox_custom_widget-0.1.0/netbox_custom_widget/utils.py +185 -0
  21. netbox_custom_widget-0.1.0/netbox_custom_widget/views.py +126 -0
  22. netbox_custom_widget-0.1.0/netbox_custom_widget/widgets.py +97 -0
  23. netbox_custom_widget-0.1.0/netbox_custom_widget.egg-info/PKG-INFO +82 -0
  24. netbox_custom_widget-0.1.0/netbox_custom_widget.egg-info/SOURCES.txt +27 -0
  25. netbox_custom_widget-0.1.0/netbox_custom_widget.egg-info/dependency_links.txt +1 -0
  26. netbox_custom_widget-0.1.0/netbox_custom_widget.egg-info/requires.txt +6 -0
  27. netbox_custom_widget-0.1.0/netbox_custom_widget.egg-info/top_level.txt +1 -0
  28. netbox_custom_widget-0.1.0/pyproject.toml +54 -0
  29. netbox_custom_widget-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,15 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.4
2
+ Name: netbox-custom-widget
3
+ Version: 0.1.0
4
+ Summary: NetBox plugin for custom API dashboard widgets - call any API and display results
5
+ Author-email: sieteunoseis <jeremy.worden@gmail.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/sieteunoseis/netbox-custom-widget
8
+ Project-URL: Repository, https://github.com/sieteunoseis/netbox-custom-widget
9
+ Project-URL: Issues, https://github.com/sieteunoseis/netbox-custom-widget/issues
10
+ Keywords: netbox,netbox-plugin,dashboard,widget,api
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Framework :: Django
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: requests>=2.28.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: black; extra == "dev"
25
+ Requires-Dist: flake8; extra == "dev"
26
+ Requires-Dist: isort; extra == "dev"
27
+ Dynamic: license-file
28
+
29
+ # NetBox Custom Widget
30
+
31
+ A NetBox plugin that provides configurable dashboard widgets for calling external APIs and displaying results. Similar to Homepage's Custom API widget.
32
+
33
+ ## Features
34
+
35
+ - Call any HTTP API endpoint and display JSON results on your NetBox dashboard
36
+ - Configurable field mappings with dot-notation for nested JSON access
37
+ - Auto-refresh via HTMX at configurable intervals
38
+ - Adaptive color coding for status values (e.g., UCCE process monitoring)
39
+ - Pre-define endpoints in plugin configuration for automatic provisioning
40
+ - Full CRUD interface for managing API endpoints
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ pip install netbox-custom-widget
46
+ ```
47
+
48
+ Add to your NetBox configuration:
49
+
50
+ ```python
51
+ PLUGINS = ['netbox_custom_widget']
52
+ ```
53
+
54
+ ## Configuration
55
+
56
+ Define API endpoints in your `plugins.py`:
57
+
58
+ ```python
59
+ PLUGINS_CONFIG = {
60
+ 'netbox_custom_widget': {
61
+ 'verify_ssl': False,
62
+ 'endpoints': [
63
+ {
64
+ 'name': 'My API Status',
65
+ 'url': 'https://api.example.com/status',
66
+ 'headers': {'Authorization': 'Bearer token123'},
67
+ 'mappings': [
68
+ {'field': 'status', 'label': 'Status', 'color': 'adaptive'},
69
+ {'field': 'uptime', 'label': 'Uptime', 'suffix': 'hours'},
70
+ ],
71
+ 'display_mode': 'list',
72
+ 'refresh_interval': 30,
73
+ },
74
+ ],
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## Requirements
80
+
81
+ - NetBox >= 4.0.0
82
+ - Python >= 3.10
@@ -0,0 +1,54 @@
1
+ # NetBox Custom Widget
2
+
3
+ A NetBox plugin that provides configurable dashboard widgets for calling external APIs and displaying results. Similar to Homepage's Custom API widget.
4
+
5
+ ## Features
6
+
7
+ - Call any HTTP API endpoint and display JSON results on your NetBox dashboard
8
+ - Configurable field mappings with dot-notation for nested JSON access
9
+ - Auto-refresh via HTMX at configurable intervals
10
+ - Adaptive color coding for status values (e.g., UCCE process monitoring)
11
+ - Pre-define endpoints in plugin configuration for automatic provisioning
12
+ - Full CRUD interface for managing API endpoints
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pip install netbox-custom-widget
18
+ ```
19
+
20
+ Add to your NetBox configuration:
21
+
22
+ ```python
23
+ PLUGINS = ['netbox_custom_widget']
24
+ ```
25
+
26
+ ## Configuration
27
+
28
+ Define API endpoints in your `plugins.py`:
29
+
30
+ ```python
31
+ PLUGINS_CONFIG = {
32
+ 'netbox_custom_widget': {
33
+ 'verify_ssl': False,
34
+ 'endpoints': [
35
+ {
36
+ 'name': 'My API Status',
37
+ 'url': 'https://api.example.com/status',
38
+ 'headers': {'Authorization': 'Bearer token123'},
39
+ 'mappings': [
40
+ {'field': 'status', 'label': 'Status', 'color': 'adaptive'},
41
+ {'field': 'uptime', 'label': 'Uptime', 'suffix': 'hours'},
42
+ ],
43
+ 'display_mode': 'list',
44
+ 'refresh_interval': 30,
45
+ },
46
+ ],
47
+ }
48
+ }
49
+ ```
50
+
51
+ ## Requirements
52
+
53
+ - NetBox >= 4.0.0
54
+ - Python >= 3.10
@@ -0,0 +1,93 @@
1
+ """
2
+ NetBox Custom Widget Plugin
3
+
4
+ Configurable dashboard widgets for calling external APIs and displaying results.
5
+ """
6
+
7
+ import logging
8
+
9
+ from django.conf import settings
10
+ from django.db.models.signals import post_migrate
11
+ from netbox.plugins import PluginConfig
12
+
13
+ __version__ = "0.1.0"
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ def provision_endpoints(sender, **kwargs):
19
+ """Create or update CustomAPIEndpoint objects from plugin configuration."""
20
+ if sender.name != "netbox_custom_widget":
21
+ return
22
+
23
+ from django.db import OperationalError, ProgrammingError
24
+
25
+ try:
26
+ from .models import CustomAPIEndpoint
27
+
28
+ config = settings.PLUGINS_CONFIG.get("netbox_custom_widget", {})
29
+ endpoints_config = config.get("endpoints", [])
30
+ global_verify_ssl = config.get("verify_ssl", True)
31
+
32
+ for ep_config in endpoints_config:
33
+ name = ep_config.get("name")
34
+ if not name:
35
+ logger.warning("Skipping endpoint config without 'name'")
36
+ continue
37
+
38
+ defaults = {
39
+ "url": ep_config.get("url", ""),
40
+ "http_method": ep_config.get("http_method", "GET"),
41
+ "headers": ep_config.get("headers", {}),
42
+ "body": ep_config.get("body", ""),
43
+ "mappings": ep_config.get("mappings", []),
44
+ "display_mode": ep_config.get("display_mode", "list"),
45
+ "refresh_interval": ep_config.get("refresh_interval", 30),
46
+ "verify_ssl": ep_config.get("verify_ssl", global_verify_ssl),
47
+ "timeout": ep_config.get("timeout", 30),
48
+ "description": ep_config.get("description", ""),
49
+ }
50
+
51
+ obj, created = CustomAPIEndpoint.objects.update_or_create(
52
+ name=name,
53
+ defaults=defaults,
54
+ )
55
+
56
+ if created:
57
+ logger.info(f"Created API endpoint: {name}")
58
+ else:
59
+ logger.debug(f"Updated API endpoint: {name}")
60
+
61
+ except (OperationalError, ProgrammingError):
62
+ pass
63
+ except Exception as e:
64
+ logger.warning(f"Could not provision endpoints: {e}")
65
+
66
+
67
+ class CustomWidgetConfig(PluginConfig):
68
+ """Plugin configuration for NetBox Custom Widget."""
69
+
70
+ name = "netbox_custom_widget"
71
+ verbose_name = "Custom Widget"
72
+ description = "Configurable dashboard widgets for calling external APIs"
73
+ version = __version__
74
+ author = "Jeremy Worden"
75
+ author_email = "jeremy.worden@gmail.com"
76
+ base_url = "custom-widget"
77
+ min_version = "4.0.0"
78
+
79
+ required_settings = []
80
+
81
+ default_settings = {
82
+ "verify_ssl": True,
83
+ "endpoints": [],
84
+ }
85
+
86
+ def ready(self):
87
+ """Register signal and import widgets."""
88
+ super().ready()
89
+ post_migrate.connect(provision_endpoints, sender=self)
90
+ from . import widgets # noqa: F401
91
+
92
+
93
+ config = CustomWidgetConfig
@@ -0,0 +1,40 @@
1
+ """API serializers for NetBox Custom Widget plugin."""
2
+
3
+ from netbox.api.serializers import NetBoxModelSerializer
4
+ from rest_framework import serializers
5
+
6
+ from ..models import CustomAPIEndpoint
7
+
8
+
9
+ class CustomAPIEndpointSerializer(NetBoxModelSerializer):
10
+ """Serializer for CustomAPIEndpoint."""
11
+
12
+ url = serializers.HyperlinkedIdentityField(
13
+ view_name="plugins-api:netbox_custom_widget-api:customapiendpoint-detail"
14
+ )
15
+ endpoint_url = serializers.CharField(source="url", read_only=True)
16
+
17
+ class Meta:
18
+ model = CustomAPIEndpoint
19
+ fields = [
20
+ "id",
21
+ "url",
22
+ "display",
23
+ "name",
24
+ "endpoint_url",
25
+ "http_method",
26
+ "headers",
27
+ "body",
28
+ "mappings",
29
+ "display_mode",
30
+ "refresh_interval",
31
+ "verify_ssl",
32
+ "timeout",
33
+ "description",
34
+ "comments",
35
+ "tags",
36
+ "custom_fields",
37
+ "created",
38
+ "last_updated",
39
+ ]
40
+ brief_fields = ["id", "url", "display", "name"]
@@ -0,0 +1,10 @@
1
+ """API URL configuration for NetBox Custom Widget plugin."""
2
+
3
+ from netbox.api.routers import NetBoxRouter
4
+
5
+ from . import views
6
+
7
+ router = NetBoxRouter()
8
+ router.register("endpoints", views.CustomAPIEndpointViewSet)
9
+
10
+ urlpatterns = router.urls
@@ -0,0 +1,15 @@
1
+ """API views for NetBox Custom Widget plugin."""
2
+
3
+ from netbox.api.viewsets import NetBoxModelViewSet
4
+
5
+ from ..filtersets import CustomAPIEndpointFilterSet
6
+ from ..models import CustomAPIEndpoint
7
+ from .serializers import CustomAPIEndpointSerializer
8
+
9
+
10
+ class CustomAPIEndpointViewSet(NetBoxModelViewSet):
11
+ """API viewset for CustomAPIEndpoint objects."""
12
+
13
+ queryset = CustomAPIEndpoint.objects.prefetch_related("tags")
14
+ serializer_class = CustomAPIEndpointSerializer
15
+ filterset_class = CustomAPIEndpointFilterSet
@@ -0,0 +1,26 @@
1
+ """Filtersets for NetBox Custom Widget plugin."""
2
+
3
+ import django_filters
4
+ from netbox.filtersets import NetBoxModelFilterSet
5
+
6
+ from .models import CustomAPIEndpoint, DisplayModeChoices, HTTPMethodChoices
7
+
8
+
9
+ class CustomAPIEndpointFilterSet(NetBoxModelFilterSet):
10
+ """Filterset for CustomAPIEndpoint model."""
11
+
12
+ name = django_filters.CharFilter(lookup_expr="icontains")
13
+ http_method = django_filters.MultipleChoiceFilter(choices=HTTPMethodChoices)
14
+ display_mode = django_filters.MultipleChoiceFilter(choices=DisplayModeChoices)
15
+
16
+ class Meta:
17
+ model = CustomAPIEndpoint
18
+ fields = ["id", "name", "http_method", "display_mode"]
19
+
20
+ def search(self, queryset, name, value):
21
+ """Search across multiple fields."""
22
+ if not value.strip():
23
+ return queryset
24
+ from django.db.models import Q
25
+
26
+ return queryset.filter(Q(name__icontains=value) | Q(url__icontains=value) | Q(description__icontains=value))
@@ -0,0 +1,91 @@
1
+ """Forms for NetBox Custom Widget plugin."""
2
+
3
+ from django import forms
4
+ from netbox.forms import NetBoxModelBulkEditForm, NetBoxModelFilterSetForm, NetBoxModelForm, NetBoxModelImportForm
5
+ from utilities.forms.fields import CommentField, TagFilterField
6
+ from utilities.forms.rendering import FieldSet
7
+
8
+ from .models import CustomAPIEndpoint, DisplayModeChoices, HTTPMethodChoices
9
+
10
+
11
+ class CustomAPIEndpointForm(NetBoxModelForm):
12
+ """Form for creating/editing CustomAPIEndpoint objects."""
13
+
14
+ comments = CommentField()
15
+
16
+ fieldsets = (
17
+ FieldSet("name", "description", name="General"),
18
+ FieldSet("url", "http_method", "headers", "body", "verify_ssl", "timeout", name="API Configuration"),
19
+ FieldSet("mappings", "display_mode", "refresh_interval", name="Display"),
20
+ FieldSet("comments", "tags", name="Details"),
21
+ )
22
+
23
+ class Meta:
24
+ model = CustomAPIEndpoint
25
+ fields = [
26
+ "name",
27
+ "url",
28
+ "http_method",
29
+ "headers",
30
+ "body",
31
+ "mappings",
32
+ "display_mode",
33
+ "refresh_interval",
34
+ "verify_ssl",
35
+ "timeout",
36
+ "description",
37
+ "comments",
38
+ "tags",
39
+ ]
40
+ widgets = {
41
+ "body": forms.Textarea(attrs={"rows": 3}),
42
+ }
43
+
44
+
45
+ class CustomAPIEndpointFilterForm(NetBoxModelFilterSetForm):
46
+ """Filter form for CustomAPIEndpoint list view."""
47
+
48
+ model = CustomAPIEndpoint
49
+
50
+ name = forms.CharField(required=False)
51
+ http_method = forms.MultipleChoiceField(choices=HTTPMethodChoices, required=False)
52
+ display_mode = forms.MultipleChoiceField(choices=DisplayModeChoices, required=False)
53
+ tag = TagFilterField(model)
54
+
55
+
56
+ class CustomAPIEndpointImportForm(NetBoxModelImportForm):
57
+ """Import form for CustomAPIEndpoint objects."""
58
+
59
+ class Meta:
60
+ model = CustomAPIEndpoint
61
+ fields = [
62
+ "name",
63
+ "url",
64
+ "http_method",
65
+ "headers",
66
+ "body",
67
+ "mappings",
68
+ "display_mode",
69
+ "refresh_interval",
70
+ "verify_ssl",
71
+ "timeout",
72
+ "description",
73
+ "comments",
74
+ "tags",
75
+ ]
76
+
77
+
78
+ class CustomAPIEndpointBulkEditForm(NetBoxModelBulkEditForm):
79
+ """Bulk edit form for CustomAPIEndpoint objects."""
80
+
81
+ model = CustomAPIEndpoint
82
+
83
+ http_method = forms.ChoiceField(choices=HTTPMethodChoices, required=False)
84
+ display_mode = forms.ChoiceField(choices=DisplayModeChoices, required=False)
85
+ refresh_interval = forms.IntegerField(required=False)
86
+ verify_ssl = forms.NullBooleanField(required=False)
87
+ timeout = forms.IntegerField(required=False)
88
+ description = forms.CharField(max_length=200, required=False)
89
+ comments = CommentField()
90
+
91
+ nullable_fields = ["description", "comments", "body"]
@@ -0,0 +1,132 @@
1
+ import django.db.models.deletion
2
+ import taggit.managers
3
+ import utilities.json
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ initial = True
10
+
11
+ dependencies = [
12
+ ("extras", "0001_initial"),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name="CustomAPIEndpoint",
18
+ fields=[
19
+ (
20
+ "id",
21
+ models.BigAutoField(
22
+ auto_created=True,
23
+ primary_key=True,
24
+ serialize=False,
25
+ ),
26
+ ),
27
+ ("created", models.DateTimeField(auto_now_add=True, null=True)),
28
+ ("last_updated", models.DateTimeField(auto_now=True, null=True)),
29
+ (
30
+ "custom_field_data",
31
+ models.JSONField(
32
+ blank=True,
33
+ default=dict,
34
+ encoder=utilities.json.CustomFieldJSONEncoder,
35
+ ),
36
+ ),
37
+ (
38
+ "name",
39
+ models.CharField(
40
+ help_text="Display name for this endpoint",
41
+ max_length=100,
42
+ unique=True,
43
+ ),
44
+ ),
45
+ (
46
+ "url",
47
+ models.CharField(
48
+ help_text="API endpoint URL",
49
+ max_length=500,
50
+ ),
51
+ ),
52
+ (
53
+ "http_method",
54
+ models.CharField(
55
+ default="GET",
56
+ max_length=10,
57
+ ),
58
+ ),
59
+ (
60
+ "headers",
61
+ models.JSONField(
62
+ blank=True,
63
+ default=dict,
64
+ help_text="Custom HTTP headers as JSON (e.g., authorization)",
65
+ ),
66
+ ),
67
+ (
68
+ "body",
69
+ models.TextField(
70
+ blank=True,
71
+ help_text="Request body for POST requests",
72
+ ),
73
+ ),
74
+ (
75
+ "mappings",
76
+ models.JSONField(
77
+ blank=True,
78
+ default=list,
79
+ help_text="Field mapping configuration as JSON array",
80
+ ),
81
+ ),
82
+ (
83
+ "display_mode",
84
+ models.CharField(
85
+ default="list",
86
+ max_length=10,
87
+ ),
88
+ ),
89
+ (
90
+ "refresh_interval",
91
+ models.PositiveIntegerField(
92
+ default=30,
93
+ help_text="Auto-refresh interval in seconds (0 to disable)",
94
+ ),
95
+ ),
96
+ (
97
+ "verify_ssl",
98
+ models.BooleanField(
99
+ default=True,
100
+ help_text="Verify SSL certificates",
101
+ ),
102
+ ),
103
+ (
104
+ "timeout",
105
+ models.PositiveIntegerField(
106
+ default=30,
107
+ help_text="Request timeout in seconds",
108
+ ),
109
+ ),
110
+ (
111
+ "description",
112
+ models.TextField(blank=True),
113
+ ),
114
+ (
115
+ "comments",
116
+ models.TextField(blank=True),
117
+ ),
118
+ (
119
+ "tags",
120
+ taggit.managers.TaggableManager(
121
+ through="extras.TaggedItem",
122
+ to="extras.Tag",
123
+ ),
124
+ ),
125
+ ],
126
+ options={
127
+ "verbose_name": "API Endpoint",
128
+ "verbose_name_plural": "API Endpoints",
129
+ "ordering": ["name"],
130
+ },
131
+ ),
132
+ ]
@@ -0,0 +1,106 @@
1
+ """Models for NetBox Custom Widget plugin."""
2
+
3
+ from django.db import models
4
+ from django.urls import reverse
5
+ from netbox.models import NetBoxModel
6
+ from utilities.choices import ChoiceSet
7
+
8
+
9
+ class HTTPMethodChoices(ChoiceSet):
10
+ """HTTP method choices."""
11
+
12
+ key = "CustomAPIEndpoint.http_method"
13
+
14
+ METHOD_GET = "GET"
15
+ METHOD_POST = "POST"
16
+
17
+ CHOICES = [
18
+ (METHOD_GET, "GET", "blue"),
19
+ (METHOD_POST, "POST", "green"),
20
+ ]
21
+
22
+
23
+ class DisplayModeChoices(ChoiceSet):
24
+ """Display mode choices for widget rendering."""
25
+
26
+ key = "CustomAPIEndpoint.display_mode"
27
+
28
+ MODE_LIST = "list"
29
+ MODE_BLOCK = "block"
30
+
31
+ CHOICES = [
32
+ (MODE_LIST, "List", "blue"),
33
+ (MODE_BLOCK, "Block", "gray"),
34
+ ]
35
+
36
+
37
+ class CustomAPIEndpoint(NetBoxModel):
38
+ """
39
+ Stores configuration for an external API endpoint.
40
+
41
+ Each endpoint defines a URL, authentication, field mappings,
42
+ and display settings for use in dashboard widgets.
43
+ """
44
+
45
+ name = models.CharField(
46
+ max_length=100,
47
+ unique=True,
48
+ help_text="Display name for this endpoint",
49
+ )
50
+ url = models.CharField(
51
+ max_length=500,
52
+ help_text="API endpoint URL",
53
+ )
54
+ http_method = models.CharField(
55
+ max_length=10,
56
+ choices=HTTPMethodChoices,
57
+ default=HTTPMethodChoices.METHOD_GET,
58
+ )
59
+ headers = models.JSONField(
60
+ default=dict,
61
+ blank=True,
62
+ help_text="Custom HTTP headers as JSON (e.g., authorization)",
63
+ )
64
+ body = models.TextField(
65
+ blank=True,
66
+ help_text="Request body for POST requests",
67
+ )
68
+ mappings = models.JSONField(
69
+ default=list,
70
+ blank=True,
71
+ help_text="Field mapping configuration as JSON array",
72
+ )
73
+ display_mode = models.CharField(
74
+ max_length=10,
75
+ choices=DisplayModeChoices,
76
+ default=DisplayModeChoices.MODE_LIST,
77
+ )
78
+ refresh_interval = models.PositiveIntegerField(
79
+ default=30,
80
+ help_text="Auto-refresh interval in seconds (0 to disable)",
81
+ )
82
+ verify_ssl = models.BooleanField(
83
+ default=True,
84
+ help_text="Verify SSL certificates",
85
+ )
86
+ timeout = models.PositiveIntegerField(
87
+ default=30,
88
+ help_text="Request timeout in seconds",
89
+ )
90
+ description = models.TextField(
91
+ blank=True,
92
+ )
93
+ comments = models.TextField(
94
+ blank=True,
95
+ )
96
+
97
+ class Meta:
98
+ ordering = ["name"]
99
+ verbose_name = "API Endpoint"
100
+ verbose_name_plural = "API Endpoints"
101
+
102
+ def __str__(self):
103
+ return self.name
104
+
105
+ def get_absolute_url(self):
106
+ return reverse("plugins:netbox_custom_widget:customapiendpoint", args=[self.pk])