Browse Source

Implemented API endpoints for ImageAttachments

Jeremy Stretch 8 years ago
parent
commit
2c1fa628a2

+ 54 - 3
netbox/extras/api/serializers.py

@@ -1,9 +1,14 @@
 from rest_framework import serializers
 from rest_framework import serializers
 
 
-from dcim.api.serializers import NestedSiteSerializer
-from extras.models import ACTION_CHOICES, Graph, GRAPH_TYPE_CHOICES, ExportTemplate, TopologyMap, UserAction
+from django.core.exceptions import ObjectDoesNotExist
+
+from dcim.api.serializers import NestedDeviceSerializer, NestedRackSerializer, NestedSiteSerializer
+from dcim.models import Device, Rack, Site
+from extras.models import (
+    ACTION_CHOICES, ExportTemplate, Graph, GRAPH_TYPE_CHOICES, ImageAttachment, TopologyMap, UserAction,
+)
 from users.api.serializers import NestedUserSerializer
 from users.api.serializers import NestedUserSerializer
-from utilities.api import ChoiceFieldSerializer
+from utilities.api import ChoiceFieldSerializer, ContentTypeFieldSerializer
 
 
 
 
 #
 #
@@ -72,6 +77,52 @@ class WritableTopologyMapSerializer(serializers.ModelSerializer):
 
 
 
 
 #
 #
+# Image attachments
+#
+
+class ImageAttachmentSerializer(serializers.ModelSerializer):
+    parent = serializers.SerializerMethodField()
+
+    class Meta:
+        model = ImageAttachment
+        fields = ['id', 'parent', 'name', 'image', 'image_height', 'image_width', 'created']
+
+    def get_parent(self, obj):
+
+        # Static mapping of models to their nested serializers
+        if isinstance(obj.parent, Device):
+            serializer = NestedDeviceSerializer
+        elif isinstance(obj.parent, Rack):
+            serializer = NestedRackSerializer
+        elif isinstance(obj.parent, Site):
+            serializer = NestedSiteSerializer
+        else:
+            raise Exception("Unexpected type of parent object for ImageAttachment")
+
+        return serializer(obj.parent, context={'request': self.context['request']}).data
+
+
+class WritableImageAttachmentSerializer(serializers.ModelSerializer):
+    content_type = ContentTypeFieldSerializer()
+
+    class Meta:
+        model = ImageAttachment
+        fields = ['id', 'content_type', 'object_id', 'name', 'image']
+
+    def validate(self, data):
+
+        # Validate that the parent object exists
+        try:
+            data['content_type'].get_object_for_this_type(id=data['object_id'])
+        except ObjectDoesNotExist:
+            raise serializers.ValidationError(
+                "Invalid parent object: {} ID {}".format(data['content_type'], data['object_id'])
+            )
+
+        return data
+
+
+#
 # User actions
 # User actions
 #
 #
 
 

+ 3 - 0
netbox/extras/api/urls.py

@@ -23,6 +23,9 @@ router.register(r'export-templates', views.ExportTemplateViewSet)
 # Topology maps
 # Topology maps
 router.register(r'topology-maps', views.TopologyMapViewSet)
 router.register(r'topology-maps', views.TopologyMapViewSet)
 
 
+# Image attachments
+router.register(r'image-attachments', views.ImageAttachmentViewSet)
+
 # Recent activity
 # Recent activity
 router.register(r'recent-activity', views.RecentActivityViewSet)
 router.register(r'recent-activity', views.RecentActivityViewSet)
 
 

+ 7 - 1
netbox/extras/api/views.py

@@ -6,7 +6,7 @@ from django.http import HttpResponse
 from django.shortcuts import get_object_or_404
 from django.shortcuts import get_object_or_404
 
 
 from extras import filters
 from extras import filters
-from extras.models import ExportTemplate, Graph, TopologyMap, UserAction
+from extras.models import ExportTemplate, Graph, ImageAttachment, TopologyMap, UserAction
 from utilities.api import WritableSerializerMixin
 from utilities.api import WritableSerializerMixin
 from . import serializers
 from . import serializers
 
 
@@ -81,6 +81,12 @@ class TopologyMapViewSet(WritableSerializerMixin, ModelViewSet):
         return response
         return response
 
 
 
 
+class ImageAttachmentViewSet(WritableSerializerMixin, ModelViewSet):
+    queryset = ImageAttachment.objects.all()
+    serializer_class = serializers.ImageAttachmentSerializer
+    write_serializer_class = serializers.WritableImageAttachmentSerializer
+
+
 class RecentActivityViewSet(ReadOnlyModelViewSet):
 class RecentActivityViewSet(ReadOnlyModelViewSet):
     """
     """
     List all UserActions to provide a log of recent activity.
     List all UserActions to provide a log of recent activity.

+ 1 - 1
netbox/extras/migrations/0005_add_imageattachment.py

@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
-# Generated by Django 1.10.6 on 2017-03-30 21:09
+# Generated by Django 1.10.6 on 2017-04-03 15:55
 from __future__ import unicode_literals
 from __future__ import unicode_literals
 
 
 from django.db import migrations, models
 from django.db import migrations, models

+ 1 - 1
netbox/extras/models.py

@@ -384,7 +384,7 @@ class ImageAttachment(models.Model):
     """
     """
     content_type = models.ForeignKey(ContentType)
     content_type = models.ForeignKey(ContentType)
     object_id = models.PositiveIntegerField()
     object_id = models.PositiveIntegerField()
-    obj = GenericForeignKey('content_type', 'object_id')
+    parent = GenericForeignKey('content_type', 'object_id')
     image = models.ImageField(upload_to=image_upload, height_field='image_height', width_field='image_width')
     image = models.ImageField(upload_to=image_upload, height_field='image_height', width_field='image_width')
     image_height = models.PositiveSmallIntegerField()
     image_height = models.PositiveSmallIntegerField()
     image_width = models.PositiveSmallIntegerField()
     image_width = models.PositiveSmallIntegerField()

+ 17 - 1
netbox/utilities/api.py

@@ -1,9 +1,10 @@
 from django.conf import settings
 from django.conf import settings
+from django.contrib.contenttypes.models import ContentType
 
 
 from rest_framework import authentication, exceptions
 from rest_framework import authentication, exceptions
 from rest_framework.exceptions import APIException
 from rest_framework.exceptions import APIException
 from rest_framework.permissions import DjangoModelPermissions, SAFE_METHODS
 from rest_framework.permissions import DjangoModelPermissions, SAFE_METHODS
-from rest_framework.serializers import Field
+from rest_framework.serializers import Field, ValidationError
 
 
 from users.models import Token
 from users.models import Token
 
 
@@ -79,6 +80,21 @@ class ChoiceFieldSerializer(Field):
         return self._choices.get(data)
         return self._choices.get(data)
 
 
 
 
+class ContentTypeFieldSerializer(Field):
+    """
+    Represent a ContentType as '<app_label>.<model>'
+    """
+    def to_representation(self, obj):
+        return "{}.{}".format(obj.app_label, obj.model)
+
+    def to_internal_value(self, data):
+        app_label, model = data.split('.')
+        try:
+            return ContentType.objects.get_by_natural_key(app_label=app_label, model=model)
+        except ContentType.DoesNotExist:
+            raise ValidationError("Invalid content type")
+
+
 class WritableSerializerMixin(object):
 class WritableSerializerMixin(object):
     """
     """
     Allow for the use of an alternate, writable serializer class for write operations (e.g. POST, PUT).
     Allow for the use of an alternate, writable serializer class for write operations (e.g. POST, PUT).