mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Added API serializer for ObjectChange
This commit is contained in:
@ -6,11 +6,12 @@ from taggit.models import Tag
|
|||||||
|
|
||||||
from dcim.api.serializers import NestedDeviceSerializer, NestedRackSerializer, NestedSiteSerializer
|
from dcim.api.serializers import NestedDeviceSerializer, NestedRackSerializer, NestedSiteSerializer
|
||||||
from dcim.models import Device, Rack, Site
|
from dcim.models import Device, Rack, Site
|
||||||
from extras.constants import ACTION_CHOICES, GRAPH_TYPE_CHOICES
|
from extras.models import ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, TopologyMap, UserAction
|
||||||
from extras.models import ExportTemplate, Graph, ImageAttachment, ReportResult, TopologyMap, UserAction
|
|
||||||
from users.api.serializers import NestedUserSerializer
|
|
||||||
from utilities.api import ChoiceFieldSerializer, ContentTypeFieldSerializer, ValidatedModelSerializer
|
|
||||||
from extras.constants import *
|
from extras.constants import *
|
||||||
|
from users.api.serializers import NestedUserSerializer
|
||||||
|
from utilities.api import (
|
||||||
|
ChoiceFieldSerializer, ContentTypeFieldSerializer, get_serializer_for_model, ValidatedModelSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -155,6 +156,31 @@ class ReportDetailSerializer(ReportSerializer):
|
|||||||
result = ReportResultSerializer()
|
result = ReportResultSerializer()
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Change logging
|
||||||
|
#
|
||||||
|
|
||||||
|
class ObjectChangeSerializer(serializers.ModelSerializer):
|
||||||
|
user = NestedUserSerializer(read_only=True)
|
||||||
|
content_type = ContentTypeFieldSerializer(read_only=True)
|
||||||
|
changed_object = serializers.SerializerMethodField(read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ObjectChange
|
||||||
|
fields = ['id', 'time', 'user', 'user_name', 'action', 'content_type', 'changed_object', 'object_data']
|
||||||
|
|
||||||
|
def get_changed_object(self, obj):
|
||||||
|
"""
|
||||||
|
Serialize a nested representation of the changed object.
|
||||||
|
"""
|
||||||
|
serializer = get_serializer_for_model(obj.changed_object, prefix='Nested')
|
||||||
|
if serializer is None:
|
||||||
|
return obj.object_repr
|
||||||
|
context = {'request': self.context['request']}
|
||||||
|
data = serializer(obj.changed_object, context=context).data
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# User actions
|
# User actions
|
||||||
#
|
#
|
||||||
|
@ -37,6 +37,9 @@ router.register(r'image-attachments', views.ImageAttachmentViewSet)
|
|||||||
# Reports
|
# Reports
|
||||||
router.register(r'reports', views.ReportViewSet, base_name='report')
|
router.register(r'reports', views.ReportViewSet, base_name='report')
|
||||||
|
|
||||||
|
# Change logging
|
||||||
|
router.register(r'object-changes', views.ObjectChangeViewSet)
|
||||||
|
|
||||||
# Recent activity
|
# Recent activity
|
||||||
router.register(r'recent-activity', views.RecentActivityViewSet)
|
router.register(r'recent-activity', views.RecentActivityViewSet)
|
||||||
|
|
||||||
|
@ -11,7 +11,9 @@ from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet
|
|||||||
from taggit.models import Tag
|
from taggit.models import Tag
|
||||||
|
|
||||||
from extras import filters
|
from extras import filters
|
||||||
from extras.models import CustomField, ExportTemplate, Graph, ImageAttachment, ReportResult, TopologyMap, UserAction
|
from extras.models import (
|
||||||
|
CustomField, ExportTemplate, Graph, ImageAttachment, ObjectChange, ReportResult, TopologyMap, UserAction,
|
||||||
|
)
|
||||||
from extras.reports import get_report, get_reports
|
from extras.reports import get_report, get_reports
|
||||||
from utilities.api import FieldChoicesViewSet, IsAuthenticatedOrLoginNotRequired, ModelViewSet
|
from utilities.api import FieldChoicesViewSet, IsAuthenticatedOrLoginNotRequired, ModelViewSet
|
||||||
from . import serializers
|
from . import serializers
|
||||||
@ -206,6 +208,19 @@ class ReportViewSet(ViewSet):
|
|||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Change logging
|
||||||
|
#
|
||||||
|
|
||||||
|
class ObjectChangeViewSet(ReadOnlyModelViewSet):
|
||||||
|
"""
|
||||||
|
Retrieve a list of recent changes.
|
||||||
|
"""
|
||||||
|
queryset = ObjectChange.objects.select_related('user')
|
||||||
|
serializer_class = serializers.ObjectChangeSerializer
|
||||||
|
filter_class = filters.ObjectChangeFilter
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# User activity
|
# User activity
|
||||||
#
|
#
|
||||||
|
@ -8,7 +8,7 @@ from taggit.models import Tag
|
|||||||
|
|
||||||
from dcim.models import Site
|
from dcim.models import Site
|
||||||
from .constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_TYPE_BOOLEAN, CF_TYPE_SELECT
|
from .constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_TYPE_BOOLEAN, CF_TYPE_SELECT
|
||||||
from .models import CustomField, Graph, ExportTemplate, TopologyMap, UserAction
|
from .models import CustomField, Graph, ExportTemplate, ObjectChange, TopologyMap, UserAction
|
||||||
|
|
||||||
|
|
||||||
class CustomFieldFilter(django_filters.Filter):
|
class CustomFieldFilter(django_filters.Filter):
|
||||||
@ -124,6 +124,25 @@ class TopologyMapFilter(django_filters.FilterSet):
|
|||||||
fields = ['name', 'slug']
|
fields = ['name', 'slug']
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectChangeFilter(django_filters.FilterSet):
|
||||||
|
q = django_filters.CharFilter(
|
||||||
|
method='search',
|
||||||
|
label='Search',
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ObjectChange
|
||||||
|
fields = ['user_name', 'action', 'content_type', 'object_repr']
|
||||||
|
|
||||||
|
def search(self, queryset, name, value):
|
||||||
|
if not value.strip():
|
||||||
|
return queryset
|
||||||
|
return queryset.filter(
|
||||||
|
Q(user_name__icontains=value) |
|
||||||
|
Q(object_repr__icontains=value)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class UserActionFilter(django_filters.FilterSet):
|
class UserActionFilter(django_filters.FilterSet):
|
||||||
username = django_filters.ModelMultipleChoiceFilter(
|
username = django_filters.ModelMultipleChoiceFilter(
|
||||||
name='user__username',
|
name='user__username',
|
||||||
|
@ -16,6 +16,8 @@ from rest_framework.response import Response
|
|||||||
from rest_framework.serializers import Field, ModelSerializer, RelatedField, ValidationError
|
from rest_framework.serializers import Field, ModelSerializer, RelatedField, ValidationError
|
||||||
from rest_framework.viewsets import GenericViewSet, ViewSet
|
from rest_framework.viewsets import GenericViewSet, ViewSet
|
||||||
|
|
||||||
|
from .utils import dynamic_import
|
||||||
|
|
||||||
WRITE_OPERATIONS = ['create', 'update', 'partial_update', 'delete']
|
WRITE_OPERATIONS = ['create', 'update', 'partial_update', 'delete']
|
||||||
|
|
||||||
|
|
||||||
@ -24,6 +26,20 @@ class ServiceUnavailable(APIException):
|
|||||||
default_detail = "Service temporarily unavailable, please try again later."
|
default_detail = "Service temporarily unavailable, please try again later."
|
||||||
|
|
||||||
|
|
||||||
|
def get_serializer_for_model(model, prefix=''):
|
||||||
|
"""
|
||||||
|
Dynamically resolve and return the appropriate serializer for a model.
|
||||||
|
"""
|
||||||
|
app_name, model_name = model._meta.label.split('.')
|
||||||
|
serializer_name = '{}.api.serializers.{}{}Serializer'.format(
|
||||||
|
app_name, prefix, model_name
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
return dynamic_import(serializer_name)
|
||||||
|
except ImportError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Authentication
|
# Authentication
|
||||||
#
|
#
|
||||||
|
Reference in New Issue
Block a user