From bb3b9331155f746580177272eb1322a64caaebc0 Mon Sep 17 00:00:00 2001 From: Alexander Haase Date: Sat, 8 Feb 2025 11:10:22 +0100 Subject: [PATCH] Fix model URL generator for plugins --- netbox/netbox/models/__init__.py | 3 +- .../migrations/0002_netboxmodel.py | 34 +++++++++++++++++++ netbox/netbox/tests/dummy_plugin/models.py | 4 ++- netbox/netbox/tests/dummy_plugin/urls.py | 1 + netbox/netbox/tests/dummy_plugin/views.py | 5 +++ netbox/netbox/tests/test_model.py | 13 +++++++ 6 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 netbox/netbox/tests/dummy_plugin/migrations/0002_netboxmodel.py create mode 100644 netbox/netbox/tests/test_model.py diff --git a/netbox/netbox/models/__init__.py b/netbox/netbox/models/__init__.py index b1f7cfd48..ca79d5e7e 100644 --- a/netbox/netbox/models/__init__.py +++ b/netbox/netbox/models/__init__.py @@ -10,6 +10,7 @@ from mptt.models import MPTTModel, TreeForeignKey from netbox.models.features import * from utilities.mptt import TreeManager from utilities.querysets import RestrictedQuerySet +from utilities.views import get_viewname __all__ = ( @@ -42,7 +43,7 @@ class NetBoxFeatureSet( return f'{settings.STATIC_URL}docs/models/{self._meta.app_label}/{self._meta.model_name}/' def get_absolute_url(self): - return reverse(f'{self._meta.app_label}:{self._meta.model_name}', args=[self.pk]) + return reverse(get_viewname(self), args=[self.pk]) # diff --git a/netbox/netbox/tests/dummy_plugin/migrations/0002_netboxmodel.py b/netbox/netbox/tests/dummy_plugin/migrations/0002_netboxmodel.py new file mode 100644 index 000000000..e03f04cc7 --- /dev/null +++ b/netbox/netbox/tests/dummy_plugin/migrations/0002_netboxmodel.py @@ -0,0 +1,34 @@ +import taggit.managers +import utilities.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dummy_plugin', '0001_initial'), + ('extras', '0122_charfield_null_choices'), + ] + + operations = [ + migrations.AddField( + model_name='dummymodel', + name='created', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='dummymodel', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder), + ), + migrations.AddField( + model_name='dummymodel', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='dummymodel', + name='tags', + field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'), + ), + ] diff --git a/netbox/netbox/tests/dummy_plugin/models.py b/netbox/netbox/tests/dummy_plugin/models.py index 9bd39a46b..09d000068 100644 --- a/netbox/netbox/tests/dummy_plugin/models.py +++ b/netbox/netbox/tests/dummy_plugin/models.py @@ -1,7 +1,9 @@ from django.db import models +from netbox.models import NetBoxModel -class DummyModel(models.Model): + +class DummyModel(NetBoxModel): name = models.CharField( max_length=20 ) diff --git a/netbox/netbox/tests/dummy_plugin/urls.py b/netbox/netbox/tests/dummy_plugin/urls.py index 9e383ffe2..65e47493d 100644 --- a/netbox/netbox/tests/dummy_plugin/urls.py +++ b/netbox/netbox/tests/dummy_plugin/urls.py @@ -6,4 +6,5 @@ from . import views urlpatterns = ( path('models/', views.DummyModelsView.as_view(), name='dummy_model_list'), path('models/add/', views.DummyModelAddView.as_view(), name='dummy_model_add'), + path('models//', views.DummyModelView.as_view(), name='dummymodel'), ) diff --git a/netbox/netbox/tests/dummy_plugin/views.py b/netbox/netbox/tests/dummy_plugin/views.py index 82f250fc1..57560fa1c 100644 --- a/netbox/netbox/tests/dummy_plugin/views.py +++ b/netbox/netbox/tests/dummy_plugin/views.py @@ -5,6 +5,7 @@ from django.http import HttpResponse from django.views.generic import View from dcim.models import Site +from netbox.views import generic from utilities.views import register_model_view from .models import DummyModel # Trigger registration of custom column @@ -18,6 +19,10 @@ class DummyModelsView(View): return HttpResponse(f"Instances: {instance_count}") +class DummyModelView(generic.ObjectView): + queryset = DummyModel.objects.all() + + class DummyModelAddView(View): def get(self, request): diff --git a/netbox/netbox/tests/test_model.py b/netbox/netbox/tests/test_model.py new file mode 100644 index 000000000..c967dceca --- /dev/null +++ b/netbox/netbox/tests/test_model.py @@ -0,0 +1,13 @@ +from django.test import TestCase + +from netbox.tests.dummy_plugin.models import DummyModel + + +class ModelTest(TestCase): + + def test_absolute_url(self): + m = DummyModel(name='Foo') + m.full_clean() + m.save() + + self.assertEqual(m.get_absolute_url(), f"/plugins/dummy-plugin/models/{m.pk}/")