Просмотр исходного кода

Closes #19722: Extend the object types REST API endpoint (#19826)

Jeremy Stretch 7 месяцев назад
Родитель
Сommit
878c624eaf
2 измененных файлов с 60 добавлено и 1 удалено
  1. 28 0
      netbox/core/models/contenttypes.py
  2. 32 1
      netbox/extras/api/serializers_/objecttypes.py

+ 28 - 0
netbox/core/models/contenttypes.py

@@ -1,7 +1,9 @@
 from django.contrib.contenttypes.models import ContentType, ContentTypeManager
 from django.db.models import Q
 
+from netbox.plugins import PluginConfig
 from netbox.registry import registry
+from utilities.string import title
 
 __all__ = (
     'ObjectType',
@@ -48,3 +50,29 @@ class ObjectType(ContentType):
 
     class Meta:
         proxy = True
+
+    @property
+    def app_labeled_name(self):
+        # Override ContentType's "app | model" representation style.
+        return f"{self.app_verbose_name} > {title(self.model_verbose_name)}"
+
+    @property
+    def app_verbose_name(self):
+        if model := self.model_class():
+            return model._meta.app_config.verbose_name
+
+    @property
+    def model_verbose_name(self):
+        if model := self.model_class():
+            return model._meta.verbose_name
+
+    @property
+    def model_verbose_name_plural(self):
+        if model := self.model_class():
+            return model._meta.verbose_name_plural
+
+    @property
+    def is_plugin_model(self):
+        if not (model := self.model_class()):
+            return  # Return null if model class is invalid
+        return isinstance(model._meta.app_config, PluginConfig)

+ 32 - 1
netbox/extras/api/serializers_/objecttypes.py

@@ -1,7 +1,13 @@
+import inspect
+
+from django.urls import NoReverseMatch, reverse
+from drf_spectacular.types import OpenApiTypes
+from drf_spectacular.utils import extend_schema_field
 from rest_framework import serializers
 
 from core.models import ObjectType
 from netbox.api.serializers import BaseModelSerializer
+from utilities.views import get_viewname
 
 __all__ = (
     'ObjectTypeSerializer',
@@ -10,7 +16,32 @@ __all__ = (
 
 class ObjectTypeSerializer(BaseModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='extras-api:objecttype-detail')
+    app_name = serializers.CharField(source='app_verbose_name', read_only=True)
+    model_name = serializers.CharField(source='model_verbose_name', read_only=True)
+    model_name_plural = serializers.CharField(source='model_verbose_name_plural', read_only=True)
+    is_plugin_model = serializers.BooleanField(read_only=True)
+    rest_api_endpoint = serializers.SerializerMethodField()
+    description = serializers.SerializerMethodField()
 
     class Meta:
         model = ObjectType
-        fields = ['id', 'url', 'display', 'app_label', 'model']
+        fields = [
+            'id', 'url', 'display', 'app_label', 'app_name', 'model', 'model_name', 'model_name_plural',
+            'is_plugin_model', 'rest_api_endpoint', 'description',
+        ]
+
+    @extend_schema_field(OpenApiTypes.STR)
+    def get_rest_api_endpoint(self, obj):
+        if not (model := obj.model_class()):
+            return
+        if viewname := get_viewname(model, action='list', rest_api=True):
+            try:
+                return reverse(viewname)
+            except NoReverseMatch:
+                return
+
+    @extend_schema_field(OpenApiTypes.STR)
+    def get_description(self, obj):
+        if not (model := obj.model_class()):
+            return
+        return inspect.getdoc(model)