Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d05b1b6ca | ||
|
|
049fb045c0 | ||
|
|
9e81b94d31 | ||
|
|
18fed2c029 | ||
|
|
a02acbc561 | ||
|
|
74d648b94d | ||
|
|
e9422d70e3 | ||
|
|
15b61fd7f9 | ||
|
|
c264536850 | ||
|
|
2dbcaa4877 | ||
|
|
6884bb3b94 | ||
|
|
bf47320864 | ||
|
|
f7bb83c913 | ||
|
|
0519796af6 | ||
|
|
19fc473286 | ||
|
|
f4188b957f | ||
|
|
51736942e7 | ||
|
|
bf63046edb | ||
|
|
72274e59b5 | ||
|
|
adea4437c9 |
+8
-15
@@ -9,24 +9,26 @@ Software Lifecycle Management
|
|||||||
Installation Guide
|
Installation Guide
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
WARNING: This plugin is only tested with Netbox 3.2 at this time.
|
||||||
|
|
||||||
When using the Docker version of Netbox, first follow the `netbox-docker
|
When using the Docker version of Netbox, first follow the `netbox-docker
|
||||||
quickstart <https://github.com/netbox-community/netbox-docker#quickstart>`__
|
quickstart <https://github.com/netbox-community/netbox-docker#quickstart>`__
|
||||||
instructions to clone the netbox-docker repo and set up the
|
instructions to clone the netbox-docker repo and set up the
|
||||||
``docker-compose.override.yml``.
|
``docker-compose.override.yml``.
|
||||||
|
|
||||||
Next, follow these instructions (based on the generic `Netbox plugin
|
Next, follow these instructions (based on the `Netbox docker variant
|
||||||
instructions <https://github.com/netbox-community/netbox-docker/wiki/Using-Netbox-Plugins>`__)
|
instructions <https://github.com/netbox-community/netbox-docker/wiki/Configuration#custom-configuration-files>`__)
|
||||||
to install the Netbox SLM plugin:
|
to install the Netbox SLM plugin:
|
||||||
|
|
||||||
1. Add ``netbox_slm`` to the ``PLUGINS`` list in
|
1. Add ``netbox_slm`` to the ``PLUGINS`` list in
|
||||||
``configuration/configuration.py``.
|
``configuration/extra.py``.
|
||||||
2. Create a ``plugin_requirements.txt`` with ``netbox-slm==0.9`` as
|
2. Create a ``plugin_requirements.txt`` with ``netbox-slm==0.98`` as
|
||||||
contents.
|
contents.
|
||||||
3. Create a ``Dockerfile-SLM`` with contents:
|
3. Create a ``Dockerfile-SLM`` with contents:
|
||||||
|
|
||||||
.. code:: dockerfile
|
.. code:: dockerfile
|
||||||
|
|
||||||
FROM netboxcommunity/netbox:v3.0.9 # The Netbox SLM plugin currently only works with v3.0.9 of Netbox due to backwards incompatible changes in newer version of Netbox
|
FROM netboxcommunity/netbox:v3.2.X
|
||||||
|
|
||||||
COPY ./plugin_requirements.txt /
|
COPY ./plugin_requirements.txt /
|
||||||
RUN /opt/netbox/venv/bin/pip install --no-warn-script-location -r /plugin_requirements.txt
|
RUN /opt/netbox/venv/bin/pip install --no-warn-script-location -r /plugin_requirements.txt
|
||||||
@@ -63,6 +65,7 @@ directory run
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
# make sure to update the version in netbox_slm/__init__.py
|
||||||
$ python setup.py sdist
|
$ python setup.py sdist
|
||||||
$ twine upload dist/*
|
$ twine upload dist/*
|
||||||
|
|
||||||
@@ -86,15 +89,6 @@ Netbox Django copy with auto-reload to develop the plugin pointing to
|
|||||||
the Dockerized postgres and redis instances, basically ignoring the
|
the Dockerized postgres and redis instances, basically ignoring the
|
||||||
netbox docker runtime server.
|
netbox docker runtime server.
|
||||||
|
|
||||||
Gotcha’s
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
*Netbox’s exception handler seems to supress initial Exceptions,
|
|
||||||
obfuscating missing imports or other Django related issues by re-raising
|
|
||||||
an opague error, e.g. netbox_slm plugin namespace doesnotexist. It’s
|
|
||||||
recommended to often check the runtime server or patch Netbox’s global
|
|
||||||
exception handler.*
|
|
||||||
|
|
||||||
Steps
|
Steps
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
@@ -104,7 +98,6 @@ Steps
|
|||||||
|
|
||||||
$ git clone https://github.com/netbox-community/netbox
|
$ git clone https://github.com/netbox-community/netbox
|
||||||
$ cd netbox
|
$ cd netbox
|
||||||
$ git checkout f5356b8 (to pin 3.0.9)
|
|
||||||
|
|
||||||
install the virtual environment
|
install the virtual environment
|
||||||
|
|
||||||
|
|||||||
+8
-15
@@ -9,24 +9,26 @@ Software Lifecycle Management
|
|||||||
Installation Guide
|
Installation Guide
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
WARNING: This plugin is only tested with Netbox 3.2 at this time.
|
||||||
|
|
||||||
When using the Docker version of Netbox, first follow the `netbox-docker
|
When using the Docker version of Netbox, first follow the `netbox-docker
|
||||||
quickstart <https://github.com/netbox-community/netbox-docker#quickstart>`__
|
quickstart <https://github.com/netbox-community/netbox-docker#quickstart>`__
|
||||||
instructions to clone the netbox-docker repo and set up the
|
instructions to clone the netbox-docker repo and set up the
|
||||||
``docker-compose.override.yml``.
|
``docker-compose.override.yml``.
|
||||||
|
|
||||||
Next, follow these instructions (based on the generic `Netbox plugin
|
Next, follow these instructions (based on the `Netbox docker variant
|
||||||
instructions <https://github.com/netbox-community/netbox-docker/wiki/Using-Netbox-Plugins>`__)
|
instructions <https://github.com/netbox-community/netbox-docker/wiki/Configuration#custom-configuration-files>`__)
|
||||||
to install the Netbox SLM plugin:
|
to install the Netbox SLM plugin:
|
||||||
|
|
||||||
1. Add ``netbox_slm`` to the ``PLUGINS`` list in
|
1. Add ``netbox_slm`` to the ``PLUGINS`` list in
|
||||||
``configuration/configuration.py``.
|
``configuration/extra.py``.
|
||||||
2. Create a ``plugin_requirements.txt`` with ``netbox-slm==0.9`` as
|
2. Create a ``plugin_requirements.txt`` with ``netbox-slm==0.98`` as
|
||||||
contents.
|
contents.
|
||||||
3. Create a ``Dockerfile-SLM`` with contents:
|
3. Create a ``Dockerfile-SLM`` with contents:
|
||||||
|
|
||||||
.. code:: dockerfile
|
.. code:: dockerfile
|
||||||
|
|
||||||
FROM netboxcommunity/netbox:v3.0.9 # The Netbox SLM plugin currently only works with v3.0.9 of Netbox due to backwards incompatible changes in newer version of Netbox
|
FROM netboxcommunity/netbox:v3.2.X
|
||||||
|
|
||||||
COPY ./plugin_requirements.txt /
|
COPY ./plugin_requirements.txt /
|
||||||
RUN /opt/netbox/venv/bin/pip install --no-warn-script-location -r /plugin_requirements.txt
|
RUN /opt/netbox/venv/bin/pip install --no-warn-script-location -r /plugin_requirements.txt
|
||||||
@@ -63,6 +65,7 @@ directory run
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
# make sure to update the version in netbox_slm/__init__.py
|
||||||
$ python setup.py sdist
|
$ python setup.py sdist
|
||||||
$ twine upload dist/*
|
$ twine upload dist/*
|
||||||
|
|
||||||
@@ -86,15 +89,6 @@ Netbox Django copy with auto-reload to develop the plugin pointing to
|
|||||||
the Dockerized postgres and redis instances, basically ignoring the
|
the Dockerized postgres and redis instances, basically ignoring the
|
||||||
netbox docker runtime server.
|
netbox docker runtime server.
|
||||||
|
|
||||||
Gotcha’s
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
*Netbox’s exception handler seems to supress initial Exceptions,
|
|
||||||
obfuscating missing imports or other Django related issues by re-raising
|
|
||||||
an opague error, e.g. netbox_slm plugin namespace doesnotexist. It’s
|
|
||||||
recommended to often check the runtime server or patch Netbox’s global
|
|
||||||
exception handler.*
|
|
||||||
|
|
||||||
Steps
|
Steps
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
@@ -104,7 +98,6 @@ Steps
|
|||||||
|
|
||||||
$ git clone https://github.com/netbox-community/netbox
|
$ git clone https://github.com/netbox-community/netbox
|
||||||
$ cd netbox
|
$ cd netbox
|
||||||
$ git checkout f5356b8 (to pin 3.0.9)
|
|
||||||
|
|
||||||
install the virtual environment
|
install the virtual environment
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class SLMConfig(PluginConfig):
|
|||||||
name = 'netbox_slm'
|
name = 'netbox_slm'
|
||||||
verbose_name = 'Software Lifecycle Management'
|
verbose_name = 'Software Lifecycle Management'
|
||||||
description = 'Software Lifecycle Management'
|
description = 'Software Lifecycle Management'
|
||||||
version = '0.1'
|
version = '0.98'
|
||||||
author = 'Hedde van der Heide'
|
author = 'Hedde van der Heide'
|
||||||
author_email = 'hedde.vanderheide@ictu.nl'
|
author_email = 'hedde.vanderheide@ictu.nl'
|
||||||
base_url = 'slm'
|
base_url = 'slm'
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from netbox.api.serializers import PrimaryModelSerializer, OrganizationalModelSerializer
|
from netbox.api.serializers import NetBoxModelSerializer
|
||||||
# from netbox_slm.api.nested_serializers import (
|
from netbox_slm.models import (
|
||||||
# NestedRecordSerializer,
|
SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation,
|
||||||
# NestedNameServerSerializer,
|
)
|
||||||
# )
|
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion
|
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductSerializer(PrimaryModelSerializer):
|
class SoftwareProductSerializer(NetBoxModelSerializer):
|
||||||
display = serializers.SerializerMethodField()
|
display = serializers.SerializerMethodField()
|
||||||
url = serializers.HyperlinkedIdentityField(
|
url = serializers.HyperlinkedIdentityField(
|
||||||
view_name="plugins-api:netbox_slm-api:softwareproduct-detail"
|
view_name="plugins-api:netbox_slm-api:softwareproduct-detail"
|
||||||
@@ -21,10 +19,10 @@ class SoftwareProductSerializer(PrimaryModelSerializer):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def get_display(self, obj):
|
def get_display(self, obj):
|
||||||
return obj.name
|
return f"{obj.manufacturer.name} - {obj.name}"
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionSerializer(PrimaryModelSerializer):
|
class SoftwareProductVersionSerializer(NetBoxModelSerializer):
|
||||||
display = serializers.SerializerMethodField()
|
display = serializers.SerializerMethodField()
|
||||||
url = serializers.HyperlinkedIdentityField(
|
url = serializers.HyperlinkedIdentityField(
|
||||||
view_name="plugins-api:netbox_slm-api:softwareproductversion-detail"
|
view_name="plugins-api:netbox_slm-api:softwareproductversion-detail"
|
||||||
@@ -38,3 +36,20 @@ class SoftwareProductVersionSerializer(PrimaryModelSerializer):
|
|||||||
|
|
||||||
def get_display(self, obj):
|
def get_display(self, obj):
|
||||||
return obj.name
|
return obj.name
|
||||||
|
|
||||||
|
|
||||||
|
class SoftwareProductInstallationSerializer(NetBoxModelSerializer):
|
||||||
|
display = serializers.SerializerMethodField()
|
||||||
|
url = serializers.HyperlinkedIdentityField(
|
||||||
|
view_name="plugins-api:netbox_slm-api:softwareproductinstallation-detail"
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = SoftwareProductInstallation
|
||||||
|
fields = [
|
||||||
|
'id', 'display', 'url', 'device', 'virtualmachine', 'software_product', 'version', 'tags',
|
||||||
|
'custom_field_data', 'created', 'last_updated',
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_display(self, obj):
|
||||||
|
return obj
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
from netbox.api import OrderedDefaultRouter
|
from netbox.api.routers import NetBoxRouter
|
||||||
from netbox_slm.api.views import (
|
from netbox_slm.api.views import (
|
||||||
NetboxSLMRootView,
|
NetboxSLMRootView,
|
||||||
SoftwareProductViewSet,
|
SoftwareProductViewSet,
|
||||||
SoftwareProductVersionViewSet,
|
SoftwareProductVersionViewSet,
|
||||||
|
SoftwareProductInstallationViewSet,
|
||||||
)
|
)
|
||||||
|
|
||||||
router = OrderedDefaultRouter()
|
router = NetBoxRouter()
|
||||||
router.APIRootView = NetboxSLMRootView
|
router.APIRootView = NetboxSLMRootView
|
||||||
|
|
||||||
router.register("softwareproducts", SoftwareProductViewSet)
|
router.register("softwareproducts", SoftwareProductViewSet)
|
||||||
router.register("softwareproductversions", SoftwareProductVersionViewSet)
|
router.register("softwareproductversions", SoftwareProductVersionViewSet)
|
||||||
|
router.register("softwareproductinstallations", SoftwareProductInstallationViewSet)
|
||||||
urlpatterns = router.urls
|
urlpatterns = router.urls
|
||||||
+16
-18
@@ -3,10 +3,16 @@ from rest_framework.decorators import action
|
|||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.routers import APIRootView
|
from rest_framework.routers import APIRootView
|
||||||
|
|
||||||
from extras.api.views import CustomFieldModelViewSet
|
from netbox.api.viewsets import NetBoxModelViewSet
|
||||||
from netbox_slm.api.serializers import SoftwareProductSerializer, SoftwareProductVersionSerializer
|
from netbox_slm.api.serializers import (
|
||||||
from netbox_slm.filters import SoftwareProductFilter, SoftwareProductVersionFilter
|
SoftwareProductSerializer, SoftwareProductVersionSerializer, SoftwareProductInstallationSerializer,
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion
|
)
|
||||||
|
from netbox_slm.filters import (
|
||||||
|
SoftwareProductFilter, SoftwareProductVersionFilter, SoftwareProductInstallationFilter,
|
||||||
|
)
|
||||||
|
from netbox_slm.models import (
|
||||||
|
SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class NetboxSLMRootView(APIRootView):
|
class NetboxSLMRootView(APIRootView):
|
||||||
@@ -18,27 +24,19 @@ class NetboxSLMRootView(APIRootView):
|
|||||||
return "NetboxSLM"
|
return "NetboxSLM"
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductViewSet(CustomFieldModelViewSet):
|
class SoftwareProductViewSet(NetBoxModelViewSet):
|
||||||
queryset = SoftwareProduct.objects.all()
|
queryset = SoftwareProduct.objects.all()
|
||||||
serializer_class = SoftwareProductSerializer
|
serializer_class = SoftwareProductSerializer
|
||||||
filterset_class = SoftwareProductFilter
|
filterset_class = SoftwareProductFilter
|
||||||
|
|
||||||
# @action(detail=True, methods=["get"])
|
|
||||||
# def records(self, request, pk=None):
|
|
||||||
# records = Record.objects.filter(zone=pk)
|
|
||||||
# serializer = RecordSerializer(records, many=True, context={"request": request})
|
|
||||||
# return Response(serializer.data)
|
|
||||||
|
|
||||||
|
class SoftwareProductVersionViewSet(NetBoxModelViewSet):
|
||||||
class SoftwareProductVersionViewSet(CustomFieldModelViewSet):
|
|
||||||
queryset = SoftwareProductVersion.objects.all()
|
queryset = SoftwareProductVersion.objects.all()
|
||||||
serializer_class = SoftwareProductVersionSerializer
|
serializer_class = SoftwareProductVersionSerializer
|
||||||
filterset_class = SoftwareProductVersionFilter
|
filterset_class = SoftwareProductVersionFilter
|
||||||
|
|
||||||
# @action(detail=True, methods=["get"])
|
|
||||||
# def records(self, request, pk=None):
|
|
||||||
# records = Record.objects.filter(zone=pk)
|
|
||||||
# serializer = RecordSerializer(records, many=True, context={"request": request})
|
|
||||||
# return Response(serializer.data)
|
|
||||||
|
|
||||||
# for reference: https://github.com/auroraresearchlab/netbox-dns/blob/main/netbox_dns/api/views.py
|
class SoftwareProductInstallationViewSet(NetBoxModelViewSet):
|
||||||
|
queryset = SoftwareProductInstallation.objects.all()
|
||||||
|
serializer_class = SoftwareProductInstallationSerializer
|
||||||
|
filterset_class = SoftwareProductInstallationFilter
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import django_filters
|
|||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from extras.filters import TagFilter
|
from extras.filters import TagFilter
|
||||||
from netbox.filtersets import PrimaryModelFilterSet
|
from netbox.filtersets import NetBoxModelFilterSet
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
||||||
from utilities.forms import DynamicModelMultipleChoiceField
|
from utilities.forms import DynamicModelMultipleChoiceField
|
||||||
|
|
||||||
|
|
||||||
class BaseFilter(PrimaryModelFilterSet):
|
class BaseFilter(NetBoxModelFilterSet):
|
||||||
q = django_filters.CharFilter(
|
q = django_filters.CharFilter(
|
||||||
method="search",
|
method="search",
|
||||||
label="Search",
|
label="Search",
|
||||||
|
|||||||
+38
-48
@@ -1,12 +1,11 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from extras.forms import (
|
from netbox.forms import (
|
||||||
CustomFieldModelForm,
|
NetBoxModelForm,
|
||||||
CustomFieldModelCSVForm,
|
NetBoxModelCSVForm,
|
||||||
AddRemoveTagsForm,
|
NetBoxModelBulkEditForm,
|
||||||
CustomFieldModelBulkEditForm,
|
NetBoxModelFilterSetForm,
|
||||||
CustomFieldModelFilterForm,
|
|
||||||
)
|
)
|
||||||
from dcim.models import Manufacturer, Device
|
from dcim.models import Manufacturer, Device
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
||||||
@@ -16,7 +15,7 @@ from utilities.forms import (
|
|||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductForm(BootstrapMixin, CustomFieldModelForm):
|
class SoftwareProductForm(NetBoxModelForm):
|
||||||
"""Form for creating a new SoftwareProduct object."""
|
"""Form for creating a new SoftwareProduct object."""
|
||||||
|
|
||||||
manufacturer = DynamicModelChoiceField(
|
manufacturer = DynamicModelChoiceField(
|
||||||
@@ -27,17 +26,12 @@ class SoftwareProductForm(BootstrapMixin, CustomFieldModelForm):
|
|||||||
# }
|
# }
|
||||||
)
|
)
|
||||||
|
|
||||||
# tags = DynamicModelMultipleChoiceField(
|
|
||||||
# queryset=Tag.objects.all(),
|
|
||||||
# required=False,
|
|
||||||
# )
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareProduct
|
model = SoftwareProduct
|
||||||
fields = ("name", "manufacturer", "description",) # "tags")
|
fields = ("name", "manufacturer", "description", "tags")
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
|
class SoftwareProductFilterForm(NetBoxModelFilterSetForm):
|
||||||
"""Form for filtering SoftwareProduct instances."""
|
"""Form for filtering SoftwareProduct instances."""
|
||||||
|
|
||||||
model = SoftwareProduct
|
model = SoftwareProduct
|
||||||
@@ -52,49 +46,44 @@ class SoftwareProductFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
|
|||||||
# tag = TagFilterField(SoftwareProduct)
|
# tag = TagFilterField(SoftwareProduct)
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductCSVForm(CustomFieldModelCSVForm):
|
class SoftwareProductCSVForm(NetBoxModelCSVForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareProduct
|
model = SoftwareProduct
|
||||||
fields = ("name",)
|
fields = ("name",)
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
|
class SoftwareProductBulkEditForm(NetBoxModelBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(
|
pk = forms.ModelMultipleChoiceField(
|
||||||
queryset=SoftwareProduct.objects.all(),
|
queryset=SoftwareProduct.objects.all(),
|
||||||
widget=forms.MultipleHiddenInput(),
|
widget=forms.MultipleHiddenInput(),
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
model = SoftwareProduct
|
||||||
nullable_fields = []
|
nullable_fields = []
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionForm(BootstrapMixin, CustomFieldModelForm):
|
class SoftwareProductVersionForm(NetBoxModelForm):
|
||||||
"""Form for creating a new SoftwareProductVersion object."""
|
"""Form for creating a new SoftwareProductVersion object."""
|
||||||
name = forms.CharField(label=_("Version"))
|
name = forms.CharField(label=_("Version"))
|
||||||
|
|
||||||
software_product = DynamicModelChoiceField(
|
software_product = DynamicModelChoiceField(
|
||||||
queryset=SoftwareProduct.objects.all(),
|
queryset=SoftwareProduct.objects.all(),
|
||||||
required=False,
|
|
||||||
widget=APISelect(
|
widget=APISelect(
|
||||||
attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}
|
attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# tags = DynamicModelMultipleChoiceField(
|
|
||||||
# queryset=Tag.objects.all(),
|
|
||||||
# required=False,
|
|
||||||
# )
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareProductVersion
|
model = SoftwareProductVersion
|
||||||
fields = ("name", "software_product",) # "tags")
|
fields = ("name", "software_product", "tags")
|
||||||
|
|
||||||
# def clean(self):
|
# def clean(self):
|
||||||
# import pdb;pdb.set_trace()
|
# import pdb;pdb.set_trace()
|
||||||
# return super(SoftwareProductVersionForm, self).clean()
|
# return super(SoftwareProductVersionForm, self).clean()
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
|
class SoftwareProductVersionFilterForm(NetBoxModelFilterSetForm):
|
||||||
"""Form for filtering SoftwareProductVersion instances."""
|
"""Form for filtering SoftwareProductVersion instances."""
|
||||||
|
|
||||||
model = SoftwareProductVersion
|
model = SoftwareProductVersion
|
||||||
@@ -109,23 +98,24 @@ class SoftwareProductVersionFilterForm(BootstrapMixin, CustomFieldModelFilterFor
|
|||||||
# tag = TagFilterField(SoftwareProduct)
|
# tag = TagFilterField(SoftwareProduct)
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionCSVForm(CustomFieldModelCSVForm):
|
class SoftwareProductVersionCSVForm(NetBoxModelCSVForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareProductVersion
|
model = SoftwareProductVersion
|
||||||
fields = ("name",)
|
fields = ("name",)
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
|
class SoftwareProductVersionBulkEditForm(NetBoxModelBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(
|
pk = forms.ModelMultipleChoiceField(
|
||||||
queryset=SoftwareProduct.objects.all(),
|
queryset=SoftwareProduct.objects.all(),
|
||||||
widget=forms.MultipleHiddenInput(),
|
widget=forms.MultipleHiddenInput(),
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
model = SoftwareProductVersion
|
||||||
nullable_fields = []
|
nullable_fields = []
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductInstallationForm(BootstrapMixin, CustomFieldModelForm):
|
class SoftwareProductInstallationForm(NetBoxModelForm):
|
||||||
"""Form for creating a new SoftwareProductInstallation object."""
|
"""Form for creating a new SoftwareProductInstallation object."""
|
||||||
|
|
||||||
device = DynamicModelChoiceField(
|
device = DynamicModelChoiceField(
|
||||||
@@ -160,23 +150,17 @@ class SoftwareProductInstallationForm(BootstrapMixin, CustomFieldModelForm):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# todo need version and device ?
|
|
||||||
|
|
||||||
# tags = DynamicModelMultipleChoiceField(
|
|
||||||
# queryset=Tag.objects.all(),
|
|
||||||
# required=False,
|
|
||||||
# )
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareProductInstallation
|
model = SoftwareProductInstallation
|
||||||
fields = ("device", "virtualmachine", "software_product", "version",) # "tags")
|
fields = ("device", "virtualmachine", "software_product", "version", "tags")
|
||||||
|
|
||||||
# def clean(self):
|
def clean(self):
|
||||||
# import pdb;pdb.set_trace()
|
if not any([self.cleaned_data['device'], self.cleaned_data['virtualmachine']]):
|
||||||
# return super(SoftwareProductInstallationForm, self).clean()
|
raise forms.ValidationError(_("Installation requires atleast one virtualmachine or device destination."))
|
||||||
|
return super(SoftwareProductInstallationForm, self).clean()
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductInstallationFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
|
class SoftwareProductInstallationFilterForm(NetBoxModelFilterSetForm):
|
||||||
"""Form for filtering SoftwareProductInstallation instances."""
|
"""Form for filtering SoftwareProductInstallation instances."""
|
||||||
|
|
||||||
model = SoftwareProductInstallation
|
model = SoftwareProductInstallation
|
||||||
@@ -186,17 +170,23 @@ class SoftwareProductInstallationFilterForm(BootstrapMixin, CustomFieldModelFilt
|
|||||||
# tag = TagFilterField(SoftwareProduct)
|
# tag = TagFilterField(SoftwareProduct)
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductInstallationCSVForm(CustomFieldModelCSVForm):
|
class SoftwareProductInstallationCSVForm(NetBoxModelCSVForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareProductInstallation
|
model = SoftwareProductInstallation
|
||||||
fields = tuple()
|
fields = tuple()
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductInstallationBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
|
class SoftwareProductInstallationBulkEditForm(NetBoxModelBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(
|
software_product = DynamicModelChoiceField(
|
||||||
queryset=SoftwareProductInstallation.objects.all(),
|
queryset=SoftwareProduct.objects.all(),
|
||||||
widget=forms.MultipleHiddenInput(),
|
required=False
|
||||||
)
|
)
|
||||||
|
version = DynamicModelChoiceField(
|
||||||
class Meta:
|
queryset=SoftwareProductVersion.objects.all(),
|
||||||
nullable_fields = []
|
required=False
|
||||||
|
)
|
||||||
|
model = SoftwareProductInstallation
|
||||||
|
fieldsets = (
|
||||||
|
(None, ('software_product', 'version',)),
|
||||||
|
)
|
||||||
|
# nullable_fields = ('',)
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 3.2.9 on 2022-01-24 08:05
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('dcim', '0133_port_colors'),
|
||||||
|
('netbox_slm', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproduct',
|
||||||
|
name='manufacturer',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='software_products', to='dcim.manufacturer'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Generated by Django 3.2.9 on 2022-04-07 12:09
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('netbox_slm', '0002_alter_softwareproduct_manufacturer'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproduct',
|
||||||
|
name='created',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproduct',
|
||||||
|
name='id',
|
||||||
|
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='created',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='id',
|
||||||
|
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductversion',
|
||||||
|
name='created',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductversion',
|
||||||
|
name='id',
|
||||||
|
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# Generated by Django 3.2.9 on 2022-04-15 07:05
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('dcim', '0153_created_datetimefield'),
|
||||||
|
('virtualization', '0029_created_datetimefield'),
|
||||||
|
('netbox_slm', '0003_auto_20220407_1209'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproduct',
|
||||||
|
name='manufacturer',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='dcim.manufacturer'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='device',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='dcim.device'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='software_product',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='netbox_slm.softwareproduct'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='version',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='netbox_slm.softwareproductversion'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='virtualmachine',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='virtualization.virtualmachine'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductversion',
|
||||||
|
name='software_product',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='netbox_slm.softwareproduct'),
|
||||||
|
),
|
||||||
|
]
|
||||||
+12
-11
@@ -1,13 +1,13 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils import safestring
|
from django.utils import safestring
|
||||||
from extras.utils import extras_features
|
# from extras.utils import extras_features # todo this changed in netbox 3.1.X and higher, currently not used but checkout why
|
||||||
from netbox.models import PrimaryModel
|
from netbox.models import NetBoxModel
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
|
|
||||||
|
|
||||||
# @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
# @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
||||||
class SoftwareProduct(PrimaryModel):
|
class SoftwareProduct(NetBoxModel):
|
||||||
"""
|
"""
|
||||||
A SoftwareProduct represents ...
|
A SoftwareProduct represents ...
|
||||||
"""
|
"""
|
||||||
@@ -17,7 +17,7 @@ class SoftwareProduct(PrimaryModel):
|
|||||||
manufacturer = models.ForeignKey(
|
manufacturer = models.ForeignKey(
|
||||||
to='dcim.Manufacturer',
|
to='dcim.Manufacturer',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='software_products'
|
null=True, blank=True
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
@@ -37,11 +37,10 @@ class SoftwareProduct(PrimaryModel):
|
|||||||
|
|
||||||
|
|
||||||
# @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
# @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
||||||
class SoftwareProductVersion(PrimaryModel):
|
class SoftwareProductVersion(NetBoxModel):
|
||||||
software_product = models.ForeignKey(
|
software_product = models.ForeignKey(
|
||||||
to='netbox_slm.SoftwareProduct',
|
to='netbox_slm.SoftwareProduct',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='softwareproduct_versions'
|
|
||||||
)
|
)
|
||||||
name = models.CharField(max_length=64)
|
name = models.CharField(max_length=64)
|
||||||
|
|
||||||
@@ -62,30 +61,26 @@ class SoftwareProductVersion(PrimaryModel):
|
|||||||
|
|
||||||
|
|
||||||
# @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
# @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
||||||
class SoftwareProductInstallation(PrimaryModel):
|
class SoftwareProductInstallation(NetBoxModel):
|
||||||
device = models.ForeignKey(
|
device = models.ForeignKey(
|
||||||
to='dcim.Device',
|
to='dcim.Device',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='softwareproduct_installations',
|
|
||||||
null=True,
|
null=True,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
virtualmachine = models.ForeignKey(
|
virtualmachine = models.ForeignKey(
|
||||||
to='virtualization.VirtualMachine',
|
to='virtualization.VirtualMachine',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='softwareproduct_installations',
|
|
||||||
null = True,
|
null = True,
|
||||||
blank = True
|
blank = True
|
||||||
)
|
)
|
||||||
software_product = models.ForeignKey(
|
software_product = models.ForeignKey(
|
||||||
to='netbox_slm.SoftwareProduct',
|
to='netbox_slm.SoftwareProduct',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='software_products'
|
|
||||||
)
|
)
|
||||||
version = models.ForeignKey(
|
version = models.ForeignKey(
|
||||||
to='netbox_slm.SoftwareProductVersion',
|
to='netbox_slm.SoftwareProductVersion',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='softwareproduct_versions'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
@@ -95,3 +90,9 @@ class SoftwareProductInstallation(PrimaryModel):
|
|||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("plugins:netbox_slm:softwareproductinstallation", kwargs={"pk": self.pk})
|
return reverse("plugins:netbox_slm:softwareproductinstallation", kwargs={"pk": self.pk})
|
||||||
|
|
||||||
|
def get_platform(self):
|
||||||
|
return self.device or self.virtualmachine
|
||||||
|
|
||||||
|
def render_type(self):
|
||||||
|
return f"{'device' if self.device else 'virtualmachine'}"
|
||||||
|
|||||||
+68
-26
@@ -1,10 +1,12 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
|
|
||||||
|
from django.db.models import Count
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
||||||
from utilities.tables import BaseTable, ChoiceFieldColumn, ToggleColumn
|
from netbox.tables import NetBoxTable, ChoiceFieldColumn, ToggleColumn, columns
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductTable(BaseTable):
|
class SoftwareProductTable(NetBoxTable):
|
||||||
"""Table for displaying SoftwareProduct objects."""
|
"""Table for displaying SoftwareProduct objects."""
|
||||||
|
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
@@ -15,11 +17,11 @@ class SoftwareProductTable(BaseTable):
|
|||||||
)
|
)
|
||||||
installations = tables.Column(accessor='get_installation_count', verbose_name='Installations')
|
installations = tables.Column(accessor='get_installation_count', verbose_name='Installations')
|
||||||
|
|
||||||
# tags = TagColumn(
|
tags = columns.TagColumn(
|
||||||
# url_name="plugins:netbox_dns:zone_list",
|
url_name="plugins:netbox_slm:softwareproduct_list",
|
||||||
# )
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = SoftwareProduct
|
model = SoftwareProduct
|
||||||
fields = (
|
fields = (
|
||||||
"pk",
|
"pk",
|
||||||
@@ -27,7 +29,7 @@ class SoftwareProductTable(BaseTable):
|
|||||||
"manufacturer",
|
"manufacturer",
|
||||||
"description",
|
"description",
|
||||||
"installations",
|
"installations",
|
||||||
# "tags",
|
"tags",
|
||||||
)
|
)
|
||||||
default_columns = (
|
default_columns = (
|
||||||
"pk",
|
"pk",
|
||||||
@@ -35,11 +37,23 @@ class SoftwareProductTable(BaseTable):
|
|||||||
"manufacturer",
|
"manufacturer",
|
||||||
"description",
|
"description",
|
||||||
"installations",
|
"installations",
|
||||||
# "tags",
|
"tags",
|
||||||
|
)
|
||||||
|
sequence = (
|
||||||
|
"manufacturer",
|
||||||
|
"name",
|
||||||
|
"description",
|
||||||
|
"installations",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def order_installations(self, queryset, is_descending):
|
||||||
|
queryset = queryset.annotate(
|
||||||
|
count=Count('softwareproductinstallation__id')
|
||||||
|
).order_by(("-" if is_descending else "") + "count")
|
||||||
|
return queryset, True
|
||||||
|
|
||||||
class SoftwareProductVersionTable(BaseTable):
|
|
||||||
|
class SoftwareProductVersionTable(NetBoxTable):
|
||||||
"""Table for displaying SoftwareProductVersion objects."""
|
"""Table for displaying SoftwareProductVersion objects."""
|
||||||
|
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
@@ -54,11 +68,11 @@ class SoftwareProductVersionTable(BaseTable):
|
|||||||
)
|
)
|
||||||
installations = tables.Column(accessor='get_installation_count', verbose_name='Installations')
|
installations = tables.Column(accessor='get_installation_count', verbose_name='Installations')
|
||||||
|
|
||||||
# tags = TagColumn(
|
tags = columns.TagColumn(
|
||||||
# url_name="plugins:netbox_dns:zone_list",
|
url_name="plugins:netbox_slm:softwareproductversion_list",
|
||||||
# )
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = SoftwareProductVersion
|
model = SoftwareProductVersion
|
||||||
fields = (
|
fields = (
|
||||||
"pk",
|
"pk",
|
||||||
@@ -66,7 +80,7 @@ class SoftwareProductVersionTable(BaseTable):
|
|||||||
"software_product",
|
"software_product",
|
||||||
"manufacturer",
|
"manufacturer",
|
||||||
"installations",
|
"installations",
|
||||||
# "tags",
|
"tags",
|
||||||
)
|
)
|
||||||
default_columns = (
|
default_columns = (
|
||||||
"pk",
|
"pk",
|
||||||
@@ -74,11 +88,23 @@ class SoftwareProductVersionTable(BaseTable):
|
|||||||
"software_product",
|
"software_product",
|
||||||
"manufacturer",
|
"manufacturer",
|
||||||
"installations",
|
"installations",
|
||||||
# "tags",
|
"tags",
|
||||||
|
)
|
||||||
|
sequence = (
|
||||||
|
"manufacturer",
|
||||||
|
"software_product",
|
||||||
|
"name",
|
||||||
|
"installations",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def order_installations(self, queryset, is_descending):
|
||||||
|
queryset = queryset.annotate(
|
||||||
|
count=Count('softwareproductinstallation__id')
|
||||||
|
).order_by(("-" if is_descending else "") + "count")
|
||||||
|
return queryset, True
|
||||||
|
|
||||||
class SoftwareProductInstallationTable(BaseTable):
|
|
||||||
|
class SoftwareProductInstallationTable(NetBoxTable):
|
||||||
"""Table for displaying SoftwareProductInstallation objects."""
|
"""Table for displaying SoftwareProductInstallation objects."""
|
||||||
|
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
@@ -91,6 +117,11 @@ class SoftwareProductInstallationTable(BaseTable):
|
|||||||
accessor=Accessor('virtualmachine'),
|
accessor=Accessor('virtualmachine'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
platform = tables.Column(
|
||||||
|
accessor='get_platform',
|
||||||
|
linkify=True
|
||||||
|
)
|
||||||
|
type = tables.Column(accessor='render_type')
|
||||||
software_product = tables.Column(
|
software_product = tables.Column(
|
||||||
accessor=Accessor('software_product'),
|
accessor=Accessor('software_product'),
|
||||||
linkify=True
|
linkify=True
|
||||||
@@ -100,26 +131,37 @@ class SoftwareProductInstallationTable(BaseTable):
|
|||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# tags = TagColumn(
|
tags = columns.TagColumn(
|
||||||
# url_name="plugins:netbox_dns:zone_list",
|
url_name="plugins:netbox_slm:softwareproductinstallation_list",
|
||||||
# )
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = SoftwareProductInstallation
|
model = SoftwareProductInstallation
|
||||||
fields = (
|
fields = (
|
||||||
"pk",
|
"pk",
|
||||||
"name",
|
"name",
|
||||||
"device",
|
"platform",
|
||||||
"virtualmachine",
|
"type",
|
||||||
"software_product",
|
"software_product",
|
||||||
"version",
|
"version",
|
||||||
# "tags",
|
"tags",
|
||||||
)
|
)
|
||||||
default_columns = (
|
default_columns = (
|
||||||
"pk",
|
"pk",
|
||||||
"device",
|
"platform",
|
||||||
"virtualmachine",
|
"type",
|
||||||
"software_product",
|
"software_product",
|
||||||
"version",
|
"version",
|
||||||
# "tags",
|
"tags",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def order_platform(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(("device" if is_descending else "virtualmachine"))
|
||||||
|
return queryset, True
|
||||||
|
|
||||||
|
def order_type(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(("device" if is_descending else "virtualmachine"))
|
||||||
|
return queryset, True
|
||||||
|
|
||||||
|
def render_software_product(self, value, **kwargs):
|
||||||
|
return f"{kwargs['record'].software_product.manufacturer.name} - {value}"
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
{% extends 'base/layout.html' %}
|
|
||||||
{% load buttons %}
|
|
||||||
{% load custom_links %}
|
|
||||||
{% load helpers %}
|
|
||||||
{% load perms %}
|
|
||||||
{% load plugins %}
|
|
||||||
{% load view_helpers %}
|
|
||||||
|
|
||||||
{% block header %}
|
|
||||||
{# Breadcrumbs #}
|
|
||||||
<nav class="breadcrumb-container px-3" aria-label="breadcrumb">
|
|
||||||
<ol class="breadcrumb">
|
|
||||||
{% block breadcrumbs %}
|
|
||||||
<li class="breadcrumb-item"><a href="{% url object|plugin_viewname:'list' %}">{{ object|meta:'verbose_name_plural'|bettertitle }}</a></li>
|
|
||||||
{% endblock %}
|
|
||||||
</ol>
|
|
||||||
</nav>
|
|
||||||
{{ block.super }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block title %}{{ object }}{% endblock %}
|
|
||||||
|
|
||||||
{% block subtitle %}
|
|
||||||
<div class="object-subtitle">
|
|
||||||
<span>Created {{ object.created|annotated_date }}</span>
|
|
||||||
<span class="separator">·</span>
|
|
||||||
<span>Updated <span title="{{ object.last_updated }}">{{ object.last_updated|timesince }}</span> ago</span>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block controls %}
|
|
||||||
{# Clone/Edit/Delete Buttons #}
|
|
||||||
<div class="controls">
|
|
||||||
<div class="control-group">
|
|
||||||
{% plugin_buttons object %}
|
|
||||||
|
|
||||||
{# Extra buttons #}
|
|
||||||
{% block extra_controls %}{% endblock %}
|
|
||||||
|
|
||||||
{% if object.clone_fields and request.user|can_add:object %}
|
|
||||||
{% plugin_clone_button object %}
|
|
||||||
{% endif %}
|
|
||||||
{% if request.user|can_change:object %}
|
|
||||||
{% plugin_edit_button object %}
|
|
||||||
{% endif %}
|
|
||||||
{% if request.user|can_delete:object %}
|
|
||||||
{% plugin_delete_button object %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="control-group">
|
|
||||||
{% custom_links object %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock controls %}
|
|
||||||
|
|
||||||
{% block tabs %}
|
|
||||||
<ul class="nav nav-tabs px-3">
|
|
||||||
{% block tab_items %}
|
|
||||||
<li class="nav-item" role="presentation">
|
|
||||||
<a class="nav-link{% if not active_tab %} active{% endif %}" href="{{ object.get_absolute_url }}">{{ object|meta:"verbose_name"|bettertitle }}</a>
|
|
||||||
</li>
|
|
||||||
{% endblock tab_items %}
|
|
||||||
{% if perms.extras.view_journalentry %}
|
|
||||||
{% with journal_viewname=object|plugin_viewname:'journal' %}
|
|
||||||
{% url journal_viewname pk=object.pk as journal_url %}
|
|
||||||
{% if journal_url %}
|
|
||||||
<li role="presentation" class="nav-item">
|
|
||||||
<a href="{{ journal_url }}" class="nav-link{% if active_tab == 'journal'%} active{% endif %}">
|
|
||||||
Journal {% badge object.journal_entries.count %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
|
||||||
{% if perms.extras.view_objectchange %}
|
|
||||||
{% with changelog_viewname=object|plugin_viewname:'changelog' %}
|
|
||||||
{% url changelog_viewname pk=object.pk as changelog_url %}
|
|
||||||
{% if changelog_url %}
|
|
||||||
<li role="presentation" class="nav-item">
|
|
||||||
<a href="{{ changelog_url }}" class="nav-link{% if active_tab == 'changelog'%} active{% endif %}">Change Log</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
{% endblock tabs %}
|
|
||||||
|
|
||||||
{% block content-wrapper %}
|
|
||||||
<div class="tab-content">
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
{% extends 'base/layout.html' %}
|
|
||||||
{% load buttons %}
|
|
||||||
{% load helpers %}
|
|
||||||
{% load render_table from django_tables2 %}
|
|
||||||
{% load static %}
|
|
||||||
{% load view_helpers %}
|
|
||||||
|
|
||||||
{% block controls %}
|
|
||||||
<div class="controls">
|
|
||||||
<div class="control-group">
|
|
||||||
{% block extra_controls %}{% endblock %}
|
|
||||||
{% if permissions.add and 'add' in action_buttons %}
|
|
||||||
{% add_button content_type.model_class|plugin_viewname:"add" %}
|
|
||||||
{% endif %}
|
|
||||||
{% if permissions.add and 'import' in action_buttons %}
|
|
||||||
{% import_button content_type.model_class|plugin_viewname:"import" %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'export' in action_buttons %}
|
|
||||||
{% export_button content_type %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock controls %}
|
|
||||||
|
|
||||||
{% block tabs %}
|
|
||||||
<ul class="nav nav-tabs px-3">
|
|
||||||
{% block tab_items %}
|
|
||||||
<li class="nav-item" role="presentation">
|
|
||||||
<button class="nav-link active" id="object-list-tab" data-bs-toggle="tab" data-bs-target="#object-list" type="button" role="tab" aria-controls="edit-form" aria-selected="true">
|
|
||||||
{% block title %}{{ content_type.model_class|meta:"verbose_name_plural"|bettertitle }}{% endblock %}
|
|
||||||
{% badge table.page.paginator.count %}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
{% if filter_form %}
|
|
||||||
<li class="nav-item" role="presentation">
|
|
||||||
<button class="nav-link" id="filters-form-tab" data-bs-toggle="tab" data-bs-target="#filters-form" type="button" role="tab" aria-controls="object-list" aria-selected="false">
|
|
||||||
Filters
|
|
||||||
{% if filter_form %}{% badge filter_form.changed_data|length bg_class="primary" %}{% endif %}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock tab_items %}
|
|
||||||
</ul>
|
|
||||||
{% endblock tabs %}
|
|
||||||
|
|
||||||
{% block content-wrapper %}
|
|
||||||
<div class="tab-content">
|
|
||||||
|
|
||||||
{# Object list #}
|
|
||||||
<div class="tab-pane show active" id="object-list" role="tabpanel" aria-labelledby="object-list-tab">
|
|
||||||
|
|
||||||
{# Applied filters #}
|
|
||||||
{% if filter_form %}
|
|
||||||
{% applied_filters filter_form request.GET %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{# "Select all" form #}
|
|
||||||
{% if table.paginator.num_pages > 1 %}
|
|
||||||
{% with bulk_edit_url=content_type.model_class|validated_viewname:"bulk_edit" bulk_delete_url=content_type.model_class|validated_viewname:"bulk_delete" %}
|
|
||||||
<div id="select-all-box" class="d-none card noprint">
|
|
||||||
<form method="post" class="form col-md-12">
|
|
||||||
{% csrf_token %}
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="float-end">
|
|
||||||
{% if bulk_edit_url and permissions.change %}
|
|
||||||
<button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm" disabled>
|
|
||||||
<span class="mdi mdi-pencil" aria-hidden="true"></span> Edit All
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if bulk_delete_url and permissions.delete %}
|
|
||||||
<button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm" disabled>
|
|
||||||
<span class="mdi mdi-trash-can-outline" aria-hidden="true"></span> Delete All
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="form-check">
|
|
||||||
<input type="checkbox" id="select-all" name="_all" class="form-check-input" />
|
|
||||||
<label for="select-all" class="form-check-label">
|
|
||||||
Select <strong>all {{ table.rows|length }} {{ table.data.verbose_name_plural }}</strong> matching query
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{# Object table controls #}
|
|
||||||
{% include 'inc/table_controls.html' with table_modal="ObjectTable_config" %}
|
|
||||||
|
|
||||||
<form method="post" class="form form-horizontal">
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="hidden" name="return_url" value="{% if return_url %}{{ return_url }}{% else %}{{ request.path }}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}{% endif %}" />
|
|
||||||
|
|
||||||
{# Object table #}
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
{% render_table table 'inc/table.html' %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Form buttons #}
|
|
||||||
{% if permissions.change or permissions.delete %}
|
|
||||||
{% with bulk_edit_url=content_type.model_class|plugin_validated_viewname:"bulk_edit" bulk_delete_url=content_type.model_class|plugin_validated_viewname:"bulk_delete" %}
|
|
||||||
<div class="noprint bulk-buttons">
|
|
||||||
<div class="bulk-button-group">
|
|
||||||
{% block bulk_buttons %}{% endblock %}
|
|
||||||
{% if bulk_edit_url and permissions.change %}
|
|
||||||
<button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm">
|
|
||||||
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit Selected
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if bulk_delete_url and permissions.delete %}
|
|
||||||
<button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm">
|
|
||||||
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete Selected
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endwith %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{# Paginator #}
|
|
||||||
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Filter form #}
|
|
||||||
{% if filter_form %}
|
|
||||||
<div class="tab-pane show" id="filters-form" role="tabpanel" aria-labelledby="filters-form-tab">
|
|
||||||
{% include 'inc/filter_list.html' %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Table config form #}
|
|
||||||
{% table_config_form table table_name="ObjectTable" %}
|
|
||||||
{% endblock content-wrapper %}
|
|
||||||
@@ -1,26 +1,21 @@
|
|||||||
{% extends 'netbox_slm/object.html' %}
|
{% extends 'generic/object.html' %}
|
||||||
|
{% load buttons %}
|
||||||
|
{% load static %}
|
||||||
{% load helpers %}
|
{% load helpers %}
|
||||||
{% load plugins %}
|
{% load plugins %}
|
||||||
{% load render_table from django_tables2 %}
|
|
||||||
{% load view_helpers %}
|
|
||||||
{% load perms %}
|
|
||||||
|
|
||||||
{% block extra_controls %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row my-3">
|
||||||
<div class="col col-md-6">
|
<div class="col col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<h5 class="card-header">
|
||||||
Software Product
|
Software Product
|
||||||
</div>
|
</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-hover attr-table">
|
<table class="table table-hover attr-table">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Name</th>
|
<th scope="row">Name</th>
|
||||||
<td>{{ object.name }}</td>
|
<td>{{ object }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Versions</th>
|
<th scope="row">Versions</th>
|
||||||
@@ -29,48 +24,23 @@
|
|||||||
<a href="{% url 'plugins:netbox_slm:softwareproductversion' pk=version.pk %}">
|
<a href="{% url 'plugins:netbox_slm:softwareproductversion' pk=version.pk %}">
|
||||||
<span class="badge" style="color: #ffffff; background-color: #9e9e9e">{{ version }}</span>
|
<span class="badge" style="color: #ffffff; background-color: #9e9e9e">{{ version }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
{% empty %}
|
||||||
|
n/a
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% include 'inc/custom_fields_panel.html' %}
|
{% include 'inc/panels/custom_fields.html' %}
|
||||||
</div>
|
{% include 'inc/panels/tags.html' %}
|
||||||
<div class="col col-md-6">
|
{# {% include 'inc/panels/comments.html' %}#}
|
||||||
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='plugins:netbox_slm:softwareproduct_list' %}
|
{% plugin_left_page object %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col col-md-12">
|
<div class="col col-md-12">
|
||||||
<div class="card">
|
{% plugin_full_width_page object %}
|
||||||
<h5 class="card-header">Versions</h5>
|
|
||||||
<div class="card-body">
|
|
||||||
<table class="table table-hover attr-table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col">NAME</th>
|
|
||||||
<th scope="col">Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for version in versions %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ version.name|truncatechars:32 }}</td>
|
|
||||||
<td class="noprint text-end text-nowrap">
|
|
||||||
{% if request.user|can_change:object %}
|
|
||||||
{% plugin_edit_button version %}
|
|
||||||
{% endif %}
|
|
||||||
{% if request.user|can_delete:object %}
|
|
||||||
{% plugin_delete_button version %}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,82 +1,49 @@
|
|||||||
{% extends 'netbox_slm/object.html' %}
|
{% extends 'generic/object.html' %}
|
||||||
|
{% load buttons %}
|
||||||
|
{% load static %}
|
||||||
{% load helpers %}
|
{% load helpers %}
|
||||||
{% load plugins %}
|
{% load plugins %}
|
||||||
{% load render_table from django_tables2 %}
|
|
||||||
{% load view_helpers %}
|
|
||||||
{% load perms %}
|
|
||||||
|
|
||||||
{% block extra_controls %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row my-3">
|
||||||
<div class="col col-md-6">
|
<div class="col col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<h5 class="card-header">
|
||||||
Software Product
|
Software Product Installation
|
||||||
</div>
|
</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-hover attr-table">
|
<table class="table table-hover attr-table">
|
||||||
|
{% if object.device %}
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Installation</th>
|
<th scope="row">Device</th>
|
||||||
<td>{{ object }}</td>
|
<td>{{ object.device }}</td>
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Virtualmachine</th>
|
||||||
|
<td>{{ object.virtualmachine }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Software Product</th>
|
||||||
|
<td>{{ object.software_product }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">bla</th>
|
<th scope="row">Version</th>
|
||||||
<td>
|
<td>{{ object.version }}</td>
|
||||||
<!-- {% for version in object.softwareproduct_versions.all %}-->
|
|
||||||
<!-- <a href="{% url 'plugins:netbox_slm:softwareproductversion' pk=version.pk %}">-->
|
|
||||||
<!-- <span class="badge" style="color: #ffffff; background-color: #9e9e9e">{{ version }}</span>-->
|
|
||||||
<!-- </a>-->
|
|
||||||
<!-- {% endfor %}-->
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% include 'inc/custom_fields_panel.html' %}
|
{% include 'inc/panels/custom_fields.html' %}
|
||||||
</div>
|
{% include 'inc/panels/tags.html' %}
|
||||||
<div class="col col-md-6">
|
{# {% include 'inc/panels/comments.html' %}#}
|
||||||
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='plugins:netbox_slm:softwareproduct_list' %}
|
{% plugin_left_page object %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-md-12">
|
||||||
|
{% plugin_full_width_page object %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--<div class="row">-->
|
|
||||||
<!-- <div class="col col-md-12">-->
|
|
||||||
<!-- <div class="card">-->
|
|
||||||
<!-- <h5 class="card-header">Records</h5>-->
|
|
||||||
<!-- <div class="card-body">-->
|
|
||||||
<!-- <table class="table table-hover attr-table table-striped">-->
|
|
||||||
<!-- <thead>-->
|
|
||||||
<!-- <tr>-->
|
|
||||||
<!-- <th scope="col">TYPE</th>-->
|
|
||||||
<!-- <th scope="col">NAME</th>-->
|
|
||||||
<!-- <th scope="col">VALUE</th>-->
|
|
||||||
<!-- <th scope="col">TTL</th>-->
|
|
||||||
<!-- <th scope="col">Actions</th>-->
|
|
||||||
<!-- </tr>-->
|
|
||||||
<!-- </thead>-->
|
|
||||||
<!-- <tbody>-->
|
|
||||||
<!-- {% for record in records %}-->
|
|
||||||
<!-- <tr>-->
|
|
||||||
<!-- <td>{{ record.type }}</td>-->
|
|
||||||
<!-- <td>{{ record.name|truncatechars:32 }}</td>-->
|
|
||||||
<!-- <td>{{ record.value|truncatechars:64 }}</td>-->
|
|
||||||
<!-- <td>{{ record.ttl }}</td>-->
|
|
||||||
<!-- <td class="noprint text-end text-nowrap">-->
|
|
||||||
<!-- {% if request.user|can_change:object %}-->
|
|
||||||
<!-- {% plugin_edit_button record %}-->
|
|
||||||
<!-- {% endif %}-->
|
|
||||||
<!-- {% if request.user|can_delete:object %}-->
|
|
||||||
<!-- {% plugin_delete_button record %}-->
|
|
||||||
<!-- {% endif %}-->
|
|
||||||
<!-- </td>-->
|
|
||||||
<!-- </tr>-->
|
|
||||||
<!-- {% endfor %}-->
|
|
||||||
<!-- </tbody>-->
|
|
||||||
<!-- </table>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!--</div>-->
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,21 +1,16 @@
|
|||||||
{% extends 'netbox_slm/object.html' %}
|
{% extends 'generic/object.html' %}
|
||||||
|
{% load buttons %}
|
||||||
|
{% load static %}
|
||||||
{% load helpers %}
|
{% load helpers %}
|
||||||
{% load plugins %}
|
{% load plugins %}
|
||||||
{% load render_table from django_tables2 %}
|
|
||||||
{% load view_helpers %}
|
|
||||||
{% load perms %}
|
|
||||||
|
|
||||||
{% block extra_controls %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row my-3">
|
||||||
<div class="col col-md-6">
|
<div class="col col-md-6">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<h5 class="card-header">
|
||||||
Software Product
|
Software Product Version
|
||||||
</div>
|
</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-hover attr-table">
|
<table class="table table-hover attr-table">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -25,58 +20,21 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Installations</th>
|
<th scope="row">Installations</th>
|
||||||
<td>
|
<td>
|
||||||
<!-- {% for version in object.softwareproduct_versions.all %}-->
|
{{ object.get_installation_count }}
|
||||||
<!-- <a href="{% url 'plugins:netbox_slm:softwareproductversion' pk=version.pk %}">-->
|
|
||||||
<!-- <span class="badge" style="color: #ffffff; background-color: #9e9e9e">{{ version }}</span>-->
|
|
||||||
<!-- </a>-->
|
|
||||||
<!-- {% endfor %}-->
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% include 'inc/custom_fields_panel.html' %}
|
{% include 'inc/panels/custom_fields.html' %}
|
||||||
</div>
|
{% include 'inc/panels/tags.html' %}
|
||||||
<div class="col col-md-6">
|
{# {% include 'inc/panels/comments.html' %}#}
|
||||||
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='plugins:netbox_slm:softwareproduct_list' %}
|
{% plugin_left_page object %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-md-12">
|
||||||
|
{% plugin_full_width_page object %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--<div class="row">-->
|
|
||||||
<!-- <div class="col col-md-12">-->
|
|
||||||
<!-- <div class="card">-->
|
|
||||||
<!-- <h5 class="card-header">Records</h5>-->
|
|
||||||
<!-- <div class="card-body">-->
|
|
||||||
<!-- <table class="table table-hover attr-table table-striped">-->
|
|
||||||
<!-- <thead>-->
|
|
||||||
<!-- <tr>-->
|
|
||||||
<!-- <th scope="col">TYPE</th>-->
|
|
||||||
<!-- <th scope="col">NAME</th>-->
|
|
||||||
<!-- <th scope="col">VALUE</th>-->
|
|
||||||
<!-- <th scope="col">TTL</th>-->
|
|
||||||
<!-- <th scope="col">Actions</th>-->
|
|
||||||
<!-- </tr>-->
|
|
||||||
<!-- </thead>-->
|
|
||||||
<!-- <tbody>-->
|
|
||||||
<!-- {% for record in records %}-->
|
|
||||||
<!-- <tr>-->
|
|
||||||
<!-- <td>{{ record.type }}</td>-->
|
|
||||||
<!-- <td>{{ record.name|truncatechars:32 }}</td>-->
|
|
||||||
<!-- <td>{{ record.value|truncatechars:64 }}</td>-->
|
|
||||||
<!-- <td>{{ record.ttl }}</td>-->
|
|
||||||
<!-- <td class="noprint text-end text-nowrap">-->
|
|
||||||
<!-- {% if request.user|can_change:object %}-->
|
|
||||||
<!-- {% plugin_edit_button record %}-->
|
|
||||||
<!-- {% endif %}-->
|
|
||||||
<!-- {% if request.user|can_delete:object %}-->
|
|
||||||
<!-- {% plugin_delete_button record %}-->
|
|
||||||
<!-- {% endif %}-->
|
|
||||||
<!-- </td>-->
|
|
||||||
<!-- </tr>-->
|
|
||||||
<!-- {% endfor %}-->
|
|
||||||
<!-- </tbody>-->
|
|
||||||
<!-- </table>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!--</div>-->
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
{% extends 'netbox_slm/object.html' %}
|
|
||||||
{% load helpers %}
|
|
||||||
{% load plugins %}
|
|
||||||
{% load render_table from django_tables2 %}
|
|
||||||
{% load view_helpers %}
|
|
||||||
{% load perms %}
|
|
||||||
|
|
||||||
{% block extra_controls %}
|
|
||||||
{% comment %}
|
|
||||||
<a href="{% url 'plugins:netbox_slm:record_add' %}?zone={{ object.id }}" class="btn btn-sm btn-primary" role="button">
|
|
||||||
<i class="mdi mdi-plus-thick"></i> Add Record
|
|
||||||
</a>
|
|
||||||
{% endcomment %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col col-md-6">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
Zone
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<table class="table table-hover attr-table">
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Name</th>
|
|
||||||
<td>{{ object.name }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Versions</th>
|
|
||||||
<td>
|
|
||||||
<ul>
|
|
||||||
<!-- {% for nameserver in object.nameservers.all %}-->
|
|
||||||
<!-- <li>-->
|
|
||||||
<!-- <a href="{% url 'plugins:netbox_slm:nameserver' pk=nameserver.pk %}">-->
|
|
||||||
<!-- {{ nameserver }}-->
|
|
||||||
<!-- </a>-->
|
|
||||||
<!-- </li>-->
|
|
||||||
<!-- {% endfor %}-->
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% include 'inc/custom_fields_panel.html' %}
|
|
||||||
</div>
|
|
||||||
<div class="col col-md-6">
|
|
||||||
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='plugins:netbox_slm:softwareproduct_list' %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--<div class="row">-->
|
|
||||||
<!-- <div class="col col-md-12">-->
|
|
||||||
<!-- <div class="card">-->
|
|
||||||
<!-- <h5 class="card-header">Records</h5>-->
|
|
||||||
<!-- <div class="card-body">-->
|
|
||||||
<!-- <table class="table table-hover attr-table table-striped">-->
|
|
||||||
<!-- <thead>-->
|
|
||||||
<!-- <tr>-->
|
|
||||||
<!-- <th scope="col">TYPE</th>-->
|
|
||||||
<!-- <th scope="col">NAME</th>-->
|
|
||||||
<!-- <th scope="col">VALUE</th>-->
|
|
||||||
<!-- <th scope="col">TTL</th>-->
|
|
||||||
<!-- <th scope="col">Actions</th>-->
|
|
||||||
<!-- </tr>-->
|
|
||||||
<!-- </thead>-->
|
|
||||||
<!-- <tbody>-->
|
|
||||||
<!-- {% for record in records %}-->
|
|
||||||
<!-- <tr>-->
|
|
||||||
<!-- <td>{{ record.type }}</td>-->
|
|
||||||
<!-- <td>{{ record.name|truncatechars:32 }}</td>-->
|
|
||||||
<!-- <td>{{ record.value|truncatechars:64 }}</td>-->
|
|
||||||
<!-- <td>{{ record.ttl }}</td>-->
|
|
||||||
<!-- <td class="noprint text-end text-nowrap">-->
|
|
||||||
<!-- {% if request.user|can_change:object %}-->
|
|
||||||
<!-- {% plugin_edit_button record %}-->
|
|
||||||
<!-- {% endif %}-->
|
|
||||||
<!-- {% if request.user|can_delete:object %}-->
|
|
||||||
<!-- {% plugin_delete_button record %}-->
|
|
||||||
<!-- {% endif %}-->
|
|
||||||
<!-- </td>-->
|
|
||||||
<!-- </tr>-->
|
|
||||||
<!-- {% endfor %}-->
|
|
||||||
<!-- </tbody>-->
|
|
||||||
<!-- </table>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!--</div>-->
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
from django import template
|
|
||||||
from django.urls import NoReverseMatch, reverse
|
|
||||||
from django import template
|
|
||||||
|
|
||||||
from utilities.templatetags.buttons import _get_viewname
|
|
||||||
from utilities.utils import prepare_cloned_fields
|
|
||||||
|
|
||||||
register = template.Library()
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter()
|
|
||||||
def plugin_validated_viewname(model, action):
|
|
||||||
"""Return the view name for :
|
|
||||||
* the given model and action if valid
|
|
||||||
* or the given model and action if valid inside a plugin
|
|
||||||
* or None if invalid.
|
|
||||||
"""
|
|
||||||
core_viewname = f"{model._meta.app_label}:{model._meta.model_name}_{action}"
|
|
||||||
plugin_viewname = (
|
|
||||||
f"plugins:{model._meta.app_label}:{model._meta.model_name}_{action}"
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
# Validate and return the view name. We don't return the actual URL yet because many of the templates
|
|
||||||
# are written to pass a name to {% url %}.
|
|
||||||
reverse(core_viewname)
|
|
||||||
return core_viewname
|
|
||||||
except NoReverseMatch:
|
|
||||||
try:
|
|
||||||
reverse(plugin_viewname)
|
|
||||||
return plugin_viewname
|
|
||||||
except NoReverseMatch:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter()
|
|
||||||
def plugin_viewname(model, action):
|
|
||||||
"""
|
|
||||||
Return the view name for the given model and action. Does not perform any validation.
|
|
||||||
"""
|
|
||||||
return f"plugins:{model._meta.app_label}:{model._meta.model_name}_{action}"
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Instance buttons
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
@register.inclusion_tag("buttons/clone.html")
|
|
||||||
def plugin_clone_button(instance):
|
|
||||||
viewname = _get_viewname(instance, "add")
|
|
||||||
url = reverse(f"plugins:{viewname}")
|
|
||||||
|
|
||||||
# Populate cloned field values
|
|
||||||
param_string = prepare_cloned_fields(instance)
|
|
||||||
if param_string:
|
|
||||||
url = f"{url}?{param_string}"
|
|
||||||
|
|
||||||
return {
|
|
||||||
"url": url,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@register.inclusion_tag("buttons/edit.html")
|
|
||||||
def plugin_edit_button(instance, **kwargs):
|
|
||||||
viewname = _get_viewname(instance, "edit")
|
|
||||||
url = reverse(f"plugins:{viewname}", kwargs={"pk": instance.pk, **kwargs})
|
|
||||||
|
|
||||||
return {
|
|
||||||
"url": url,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@register.inclusion_tag("buttons/delete.html")
|
|
||||||
def plugin_delete_button(instance, **kwargs):
|
|
||||||
viewname = _get_viewname(instance, "delete")
|
|
||||||
url = reverse(f"plugins:{viewname}", kwargs={"pk": instance.pk, **kwargs})
|
|
||||||
|
|
||||||
return {
|
|
||||||
"url": url,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# List buttons
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
@register.inclusion_tag("buttons/add.html")
|
|
||||||
def plugin_add_button(url):
|
|
||||||
url = reverse(f"plugins:{url}")
|
|
||||||
|
|
||||||
return {
|
|
||||||
"add_url": url,
|
|
||||||
}
|
|
||||||
+27
-14
@@ -1,5 +1,5 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
from extras.views import ObjectChangeLogView
|
from netbox.views.generic import ObjectChangeLogView
|
||||||
from netbox_slm import views
|
from netbox_slm import views
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
||||||
|
|
||||||
@@ -9,9 +9,11 @@ urlpatterns = [
|
|||||||
path("software-products/add/", views.SoftwareProductEditView.as_view(), name='softwareproduct_add'),
|
path("software-products/add/", views.SoftwareProductEditView.as_view(), name='softwareproduct_add'),
|
||||||
path("software-products/import/", views.SoftwareProductBulkImportView.as_view(), name="softwareproduct_import"),
|
path("software-products/import/", views.SoftwareProductBulkImportView.as_view(), name="softwareproduct_import"),
|
||||||
path("software-products/edit/", views.SoftwareProductBulkEditView.as_view(), name="softwareproduct_bulk_edit"),
|
path("software-products/edit/", views.SoftwareProductBulkEditView.as_view(), name="softwareproduct_bulk_edit"),
|
||||||
path("software-products/delete/", views.SoftwareProductBulkDeleteView.as_view(), name="softwareproduct_bulk_delete"),
|
path("software-products/delete/", views.SoftwareProductBulkDeleteView.as_view(),
|
||||||
|
name="softwareproduct_bulk_delete"),
|
||||||
path("software-products/<int:pk>/", views.SoftwareProductView.as_view(), name="softwareproduct"),
|
path("software-products/<int:pk>/", views.SoftwareProductView.as_view(), name="softwareproduct"),
|
||||||
path("software-products/<int:pk>/delete/", views.SoftwareProductDeleteView.as_view(), name="softwareproduct_delete"),
|
path("software-products/<int:pk>/delete/", views.SoftwareProductDeleteView.as_view(),
|
||||||
|
name="softwareproduct_delete"),
|
||||||
path("software-products/<int:pk>/edit/", views.SoftwareProductEditView.as_view(), name="softwareproduct_edit"),
|
path("software-products/<int:pk>/edit/", views.SoftwareProductEditView.as_view(), name="softwareproduct_edit"),
|
||||||
path(
|
path(
|
||||||
"software-products/<int:pk>/changelog/",
|
"software-products/<int:pk>/changelog/",
|
||||||
@@ -23,11 +25,14 @@ urlpatterns = [
|
|||||||
# Software Product Versions
|
# Software Product Versions
|
||||||
path("versions/", views.SoftwareProductVersionListView.as_view(), name='softwareproductversion_list'),
|
path("versions/", views.SoftwareProductVersionListView.as_view(), name='softwareproductversion_list'),
|
||||||
path("versions/add/", views.SoftwareProductVersionEditView.as_view(), name='softwareproductversion_add'),
|
path("versions/add/", views.SoftwareProductVersionEditView.as_view(), name='softwareproductversion_add'),
|
||||||
path("versions/import/", views.SoftwareProductVersionBulkImportView.as_view(), name="softwareproductversion_import"),
|
path("versions/import/", views.SoftwareProductVersionBulkImportView.as_view(),
|
||||||
|
name="softwareproductversion_import"),
|
||||||
path("versions/edit/", views.SoftwareProductVersionBulkEditView.as_view(), name="softwareproductversion_bulk_edit"),
|
path("versions/edit/", views.SoftwareProductVersionBulkEditView.as_view(), name="softwareproductversion_bulk_edit"),
|
||||||
path("versions/delete/", views.SoftwareProductVersionBulkDeleteView.as_view(), name="softwareproductversion_bulk_delete"),
|
path("versions/delete/", views.SoftwareProductVersionBulkDeleteView.as_view(),
|
||||||
|
name="softwareproductversion_bulk_delete"),
|
||||||
path("versions/<int:pk>/", views.SoftwareProductVersionView.as_view(), name="softwareproductversion"),
|
path("versions/<int:pk>/", views.SoftwareProductVersionView.as_view(), name="softwareproductversion"),
|
||||||
path("versions/<int:pk>/delete/", views.SoftwareProductVersionDeleteView.as_view(), name="softwareproductversion_delete"),
|
path("versions/<int:pk>/delete/", views.SoftwareProductVersionDeleteView.as_view(),
|
||||||
|
name="softwareproductversion_delete"),
|
||||||
path("versions/<int:pk>/edit/", views.SoftwareProductVersionEditView.as_view(), name="softwareproductversion_edit"),
|
path("versions/<int:pk>/edit/", views.SoftwareProductVersionEditView.as_view(), name="softwareproductversion_edit"),
|
||||||
path(
|
path(
|
||||||
"versions/<int:pk>/changelog/",
|
"versions/<int:pk>/changelog/",
|
||||||
@@ -37,14 +42,22 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
|
|
||||||
# Software Product Versions
|
# Software Product Versions
|
||||||
path("installations/", views.SoftwareProductInstallationListView.as_view(), name='softwareproductinstallation_list'),
|
path("installations/", views.SoftwareProductInstallationListView.as_view(),
|
||||||
path("installations/add/", views.SoftwareProductInstallationEditView.as_view(), name='softwareproductinstallation_add'),
|
name='softwareproductinstallation_list'),
|
||||||
path("installations/import/", views.SoftwareProductInstallationBulkImportView.as_view(), name="softwareproductinstallation_import"),
|
path("installations/add/", views.SoftwareProductInstallationEditView.as_view(),
|
||||||
path("installations/edit/", views.SoftwareProductInstallationBulkEditView.as_view(), name="softwareproductinstallation_bulk_edit"),
|
name='softwareproductinstallation_add'),
|
||||||
path("installations/delete/", views.SoftwareProductInstallationBulkDeleteView.as_view(), name="softwareproductinstallation_bulk_delete"),
|
path("installations/import/", views.SoftwareProductInstallationBulkImportView.as_view(),
|
||||||
path("installations/<int:pk>/", views.SoftwareProductInstallationView.as_view(), name="softwareproductinstallation"),
|
name="softwareproductinstallation_import"),
|
||||||
path("installations/<int:pk>/delete/", views.SoftwareProductInstallationDeleteView.as_view(), name="softwareproductinstallation_delete"),
|
path("installations/edit/", views.SoftwareProductInstallationBulkEditView.as_view(),
|
||||||
path("installations/<int:pk>/edit/", views.SoftwareProductInstallationEditView.as_view(), name="softwareproductinstallation_edit"),
|
name="softwareproductinstallation_bulk_edit"),
|
||||||
|
path("installations/delete/", views.SoftwareProductInstallationBulkDeleteView.as_view(),
|
||||||
|
name="softwareproductinstallation_bulk_delete"),
|
||||||
|
path("installations/<int:pk>/", views.SoftwareProductInstallationView.as_view(),
|
||||||
|
name="softwareproductinstallation"),
|
||||||
|
path("installations/<int:pk>/delete/", views.SoftwareProductInstallationDeleteView.as_view(),
|
||||||
|
name="softwareproductinstallation_delete"),
|
||||||
|
path("installations/<int:pk>/edit/", views.SoftwareProductInstallationEditView.as_view(),
|
||||||
|
name="softwareproductinstallation_edit"),
|
||||||
path(
|
path(
|
||||||
"installations/<int:pk>/changelog/",
|
"installations/<int:pk>/changelog/",
|
||||||
ObjectChangeLogView.as_view(),
|
ObjectChangeLogView.as_view(),
|
||||||
|
|||||||
+11
-11
@@ -19,7 +19,7 @@ class SoftwareProductListView(generic.ObjectListView):
|
|||||||
filterset = SoftwareProductFilter
|
filterset = SoftwareProductFilter
|
||||||
filterset_form = SoftwareProductFilterForm
|
filterset_form = SoftwareProductFilterForm
|
||||||
table = SoftwareProductTable
|
table = SoftwareProductTable
|
||||||
template_name = "netbox_slm/object_list.html"
|
# template_name = "netbox_slm/object_list.html"
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductView(generic.ObjectView):
|
class SoftwareProductView(generic.ObjectView):
|
||||||
@@ -28,7 +28,7 @@ class SoftwareProductView(generic.ObjectView):
|
|||||||
queryset = SoftwareProduct.objects.all()
|
queryset = SoftwareProduct.objects.all()
|
||||||
|
|
||||||
def get_extra_context(self, request, instance):
|
def get_extra_context(self, request, instance):
|
||||||
versions = instance.softwareproduct_versions.all()
|
versions = instance.softwareproductversion_set.all()
|
||||||
return {"versions": versions}
|
return {"versions": versions}
|
||||||
|
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ class SoftwareProductEditView(generic.ObjectEditView):
|
|||||||
"""View for editing and creating a SoftwareProduct instance."""
|
"""View for editing and creating a SoftwareProduct instance."""
|
||||||
|
|
||||||
queryset = SoftwareProduct.objects.all()
|
queryset = SoftwareProduct.objects.all()
|
||||||
model_form = SoftwareProductForm
|
form = SoftwareProductForm
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductDeleteView(generic.ObjectDeleteView):
|
class SoftwareProductDeleteView(generic.ObjectDeleteView):
|
||||||
@@ -70,7 +70,7 @@ class SoftwareProductVersionListView(generic.ObjectListView):
|
|||||||
filterset = SoftwareProductVersionFilter
|
filterset = SoftwareProductVersionFilter
|
||||||
filterset_form = SoftwareProductVersionFilterForm
|
filterset_form = SoftwareProductVersionFilterForm
|
||||||
table = SoftwareProductVersionTable
|
table = SoftwareProductVersionTable
|
||||||
template_name = "netbox_slm/object_list.html"
|
# template_name = "netbox_slm/object_list.html"
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionView(generic.ObjectView):
|
class SoftwareProductVersionView(generic.ObjectView):
|
||||||
@@ -78,16 +78,16 @@ class SoftwareProductVersionView(generic.ObjectView):
|
|||||||
|
|
||||||
queryset = SoftwareProductVersion.objects.all()
|
queryset = SoftwareProductVersion.objects.all()
|
||||||
|
|
||||||
# def get_extra_context(self, request, instance):
|
def get_extra_context(self, request, instance):
|
||||||
# records = instance.record_set.all()
|
installation_count = instance.get_installation_count()
|
||||||
# return {"records": records}
|
return {"installations": installation_count}
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionEditView(generic.ObjectEditView):
|
class SoftwareProductVersionEditView(generic.ObjectEditView):
|
||||||
"""View for editing and creating a SoftwareProductVersion instance."""
|
"""View for editing and creating a SoftwareProductVersion instance."""
|
||||||
|
|
||||||
queryset = SoftwareProductVersion.objects.all()
|
queryset = SoftwareProductVersion.objects.all()
|
||||||
model_form = SoftwareProductVersionForm
|
form = SoftwareProductVersionForm
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionDeleteView(generic.ObjectDeleteView):
|
class SoftwareProductVersionDeleteView(generic.ObjectDeleteView):
|
||||||
@@ -121,13 +121,13 @@ class SoftwareProductInstallationListView(generic.ObjectListView):
|
|||||||
filterset = SoftwareProductInstallationFilter
|
filterset = SoftwareProductInstallationFilter
|
||||||
filterset_form = SoftwareProductInstallationFilterForm
|
filterset_form = SoftwareProductInstallationFilterForm
|
||||||
table = SoftwareProductInstallationTable
|
table = SoftwareProductInstallationTable
|
||||||
template_name = "netbox_slm/object_list.html"
|
# template_name = "netbox_slm/object_list.html"
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductInstallationView(generic.ObjectView):
|
class SoftwareProductInstallationView(generic.ObjectView):
|
||||||
"""Display SoftwareProductInstallation details"""
|
"""Display SoftwareProductInstallation details"""
|
||||||
|
|
||||||
queryset = SoftwareProductVersion.objects.all()
|
queryset = SoftwareProductInstallation.objects.all()
|
||||||
|
|
||||||
# def get_extra_context(self, request, instance):
|
# def get_extra_context(self, request, instance):
|
||||||
# records = instance.record_set.all()
|
# records = instance.record_set.all()
|
||||||
@@ -138,7 +138,7 @@ class SoftwareProductInstallationEditView(generic.ObjectEditView):
|
|||||||
"""View for editing and creating a SoftwareProductInstallation instance."""
|
"""View for editing and creating a SoftwareProductInstallation instance."""
|
||||||
|
|
||||||
queryset = SoftwareProductInstallation.objects.all()
|
queryset = SoftwareProductInstallation.objects.all()
|
||||||
model_form = SoftwareProductInstallationForm
|
form = SoftwareProductInstallationForm
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductInstallationDeleteView(generic.ObjectDeleteView):
|
class SoftwareProductInstallationDeleteView(generic.ObjectDeleteView):
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = netbox-slm
|
name = netbox-slm
|
||||||
version = 0.92
|
version = 0.98
|
||||||
description = Software Lifecycle Management Netbox Plugin.
|
description = Software Lifecycle Management Netbox Plugin.
|
||||||
# long_description = file: README.rst
|
# long_description = file: README.rst
|
||||||
# long_description_content_type='text/x-rst'
|
# long_description_content_type='text/x-rst'
|
||||||
@@ -16,6 +16,7 @@ classifiers =
|
|||||||
Programming Language :: Python
|
Programming Language :: Python
|
||||||
Programming Language :: Python :: 3
|
Programming Language :: Python :: 3
|
||||||
Programming Language :: Python :: 3 :: Only
|
Programming Language :: Python :: 3 :: Only
|
||||||
|
Programming Language :: Python :: 3.7
|
||||||
Programming Language :: Python :: 3.8
|
Programming Language :: Python :: 3.8
|
||||||
Programming Language :: Python :: 3.9
|
Programming Language :: Python :: 3.9
|
||||||
Topic :: Internet :: WWW/HTTP
|
Topic :: Internet :: WWW/HTTP
|
||||||
@@ -24,4 +25,4 @@ classifiers =
|
|||||||
[options]
|
[options]
|
||||||
include_package_data = true
|
include_package_data = true
|
||||||
packages = find:
|
packages = find:
|
||||||
python_requires = >=3.6
|
python_requires = >=3.7
|
||||||
|
|||||||
Reference in New Issue
Block a user